diff --git a/ChangeLog b/ChangeLog index 4c92419f4..1db476bb4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2008-02-09 Brian Matherly + * src/ReportBase/_WebReportDialog.py: + * src/ReportBase/_ReportDialog.py: + * src/ReportBase/Makefile.am + * src/ReportBase/_BareReportDialog.py: + * src/ReportBase/_ReportOptions.py: + * src/plugins/WebCal.py: + * src/plugins/BookReport.py: + * src/plugins/NarrativeWeb.py: + * src/PluginUtils/__init__.py: + * src/PluginUtils/_MenuOptions.py: + * src/PluginUtils/_GuiOptions.py: + * src/BaseDoc.py: + Web Calendar and Narrative Web report now use Menu Options. + 2008-02-08 Raphael Ackermann * src/Editors/_EditEvent.py: * src/Editors/_EditFamily.py: diff --git a/src/BaseDoc.py b/src/BaseDoc.py index 8fb3b62bf..24a43ba39 100644 --- a/src/BaseDoc.py +++ b/src/BaseDoc.py @@ -1052,6 +1052,18 @@ class StyleSheet: self.draw_styles = {} self.table_styles = {} self.cell_styles = {} + + def is_empty(self): + "Checks if any styles are defined" + style_count = len(self.para_styles) + \ + len(self.draw_styles) + \ + len(self.table_styles) + \ + len(self.cell_styles) + print style_count + if style_count > 0: + return False + else: + return True def add_paragraph_style(self, name, style): """ diff --git a/src/PluginUtils/_GuiOptions.py b/src/PluginUtils/_GuiOptions.py index 588a4d7a3..de2418d10 100644 --- a/src/PluginUtils/_GuiOptions.py +++ b/src/PluginUtils/_GuiOptions.py @@ -28,14 +28,22 @@ Specific option handling for a GUI. # #------------------------------------------------------------------------ from gettext import gettext as _ +import os +import sys + +#------------------------------------------------------------------------- +# +# gtk modules +# +#------------------------------------------------------------------------- +import gtk +import gobject #------------------------------------------------------------------------- # # gramps modules # #------------------------------------------------------------------------- -import gtk -import gobject import Utils import GrampsWidgets import ManagedWindow @@ -164,7 +172,7 @@ class GuiStringOption(gtk.Entry): """ Handle the change of the value. """ - self.__option.set_value( self.__entry.get_text() ) + self.__option.set_value( self.get_text() ) #------------------------------------------------------------------------- # @@ -591,6 +599,165 @@ class GuiFamilyOption(gtk.HBox): avail = self.__option.get_available() self.set_sensitive(avail) +#------------------------------------------------------------------------- +# +# GuiNoteOption class +# +#------------------------------------------------------------------------- +class GuiNoteOption(gtk.HBox): + """ + This class displays an option that allows a note from the + database to be selected. + """ + def __init__(self, option, dbstate, uistate, track, tooltip): + """ + @param option: The option to display. + @type option: MenuOption.NoteOption + @return: nothing + """ + gtk.HBox.__init__(self) + self.__option = option + self.__dbstate = dbstate + self.__db = dbstate.get_database() + self.__uistate = uistate + self.__track = track + self.__note_label = gtk.Label() + self.__note_label.set_alignment(0.0, 0.5) + + pevt = gtk.EventBox() + pevt.add(self.__note_label) + note_button = GrampsWidgets.SimpleButton(gtk.STOCK_INDEX, + self.__get_note_clicked) + note_button.set_relief(gtk.RELIEF_NORMAL) + + self.pack_start(pevt, False) + self.pack_end(note_button, False) + + # Initialize to the current value + nid = self.__option.get_value() + note = self.__db.get_note_from_gramps_id(nid) + self.__update_note(note) + + tooltip.set_tip(pevt, self.__option.get_help()) + tooltip.set_tip(note_button, _('Select an existing note')) + + self.__option.connect('avail-changed', self.__update_avail) + self.__update_avail() + + def __get_note_clicked(self, obj): # IGNORE:W0613 - obj is unused + """ + Handle the button to choose a different note. + """ + select_class = selector_factory('Note') + sel = select_class(self.__dbstate, self.__uistate, self.__track) + note = sel.run() + self.__update_note(note) + + def __update_note(self, note): + """ + Update the currently selected note. + """ + if note: + note_id = note.get_gramps_id() + txt = " ".join(note.get(markup=False).split()) + if len(txt) > 35: + txt = txt[:35]+"..." + else: + txt = txt + txt = "%s [%s]" % (txt, note_id) + + self.__note_label.set_text( txt ) + self.__option.set_value(note_id) + else: + txt = "%s" % _('No note given, click button to select one') + self.__note_label.set_text( txt ) + self.__note_label.set_use_markup(True) + self.__option.set_value("") + + def __update_avail(self): + """ + Update the availability (sensitivity) of this widget. + """ + avail = self.__option.get_available() + self.set_sensitive(avail) + +#------------------------------------------------------------------------- +# +# GuiMediaOption class +# +#------------------------------------------------------------------------- +class GuiMediaOption(gtk.HBox): + """ + This class displays an option that allows a media object from the + database to be selected. + """ + def __init__(self, option, dbstate, uistate, track, tooltip): + """ + @param option: The option to display. + @type option: MenuOption.MediaOption + @return: nothing + """ + gtk.HBox.__init__(self) + self.__option = option + self.__dbstate = dbstate + self.__db = dbstate.get_database() + self.__uistate = uistate + self.__track = track + self.__media_label = gtk.Label() + self.__media_label.set_alignment(0.0, 0.5) + + pevt = gtk.EventBox() + pevt.add(self.__media_label) + media_button = GrampsWidgets.SimpleButton(gtk.STOCK_INDEX, + self.__get_media_clicked) + media_button.set_relief(gtk.RELIEF_NORMAL) + + self.pack_start(pevt, False) + self.pack_end(media_button, False) + + # Initialize to the current value + mid = self.__option.get_value() + media = self.__db.get_object_from_gramps_id(mid) + self.__update_media(media) + + tooltip.set_tip(pevt, self.__option.get_help()) + tooltip.set_tip(media_button, _('Select an existing media object')) + + self.__option.connect('avail-changed', self.__update_avail) + self.__update_avail() + + def __get_media_clicked(self, obj): # IGNORE:W0613 - obj is unused + """ + Handle the button to choose a different note. + """ + select_class = selector_factory('MediaObject') + sel = select_class(self.__dbstate, self.__uistate, self.__track) + media = sel.run() + self.__update_media(media) + + def __update_media(self, media): + """ + Update the currently selected media. + """ + if media: + media_id = media.get_gramps_id() + txt = "%s [%s]" % (media.get_description(), media_id) + + self.__media_label.set_text( txt ) + self.__option.set_value(media_id) + else: + txt = "%s" % _('No image given, click button to select one') + self.__media_label.set_text( txt ) + self.__media_label.set_use_markup(True) + self.__option.set_value("") + + def __update_avail(self): + """ + Update the availability (sensitivity) of this widget. + """ + avail = self.__option.get_available() + self.set_sensitive(avail) + #------------------------------------------------------------------------- # # GuiPersonListOption class @@ -868,6 +1035,102 @@ class GuiSurnameColourOption(gtk.HBox): i = self.__model.get_iter(path) self.__model.remove(i) self.__value_changed() + +#------------------------------------------------------------------------- +# +# GuiDestinationOption class +# +#------------------------------------------------------------------------- +class GuiDestinationOption(gtk.HBox): + """ + This class displays an option that is a simple one-line string. + """ + def __init__(self, option, dbstate, uistate, track, tooltip): + """ + @param option: The option to display. + @type option: MenuOption.StringOption + @return: nothing + """ + gtk.HBox.__init__(self) + self.__option = option + self.__entry = gtk.Entry() + self.__entry.set_text( self.__option.get_value() ) + self.__entry.connect('changed', self.__text_changed) + + self.__button = gtk.Button() + img = gtk.Image() + img.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON) + self.__button.add(img) + self.__button.connect('clicked', self.__select_file) + + self.pack_start(self.__entry, True, True) + self.pack_end(self.__button, False, False) + + tooltip.set_tip(self, self.__option.get_help()) + + self.__option.connect('options-changed', self.__option_changed) + + def __text_changed(self, obj): # IGNORE:W0613 - obj is unused + """ + Handle the change of the value. + """ + self.__option.set_value( self.__entry.get_text() ) + + def __select_file(self, obj): + """ + Handle the user's request to select a file (or directory). + """ + if self.__option.get_directory_entry(): + my_action = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER + else: + my_action = gtk.FILE_CHOOSER_ACTION_SAVE + + fcd = gtk.FileChooserDialog(_("Save As"), action=my_action, + buttons=(gtk.STOCK_CANCEL, + gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, + gtk.RESPONSE_OK)) + + name = os.path.abspath(self.__option.get_value()) + if self.__option.get_directory_entry(): + while not os.path.isdir(name): + # Keep looking up levels to find a valid drive. + name, tail = os.path.split(name) + if not name: + # Avoid infinite loops + name = os.getcwd() + fcd.set_current_folder(name) + else: + fcd.set_current_name(name) + + status = fcd.run() + if status == gtk.RESPONSE_OK: + path = unicode(fcd.get_filename(), sys.getfilesystemencoding()) + print path + if path: + if not self.__option.get_directory_entry() and \ + not path.endswith(self.__option.get_extension()): + path = path + self.__option.get_extension() + self.__entry.set_text(path) + self.__option.set_value(path) + fcd.destroy() + + def __option_changed(self): + """ + Handle a change of the option. + """ + extension = self.__option.get_extension() + directory = self.__option.get_directory_entry() + value = self.__option.get_value() + + if not directory and not value.endswith(extension): + value = value + extension + self.__option.set_value(value) + elif directory and value.endswith(extension): + value = value[:-len(extension)] + self.__option.set_value(value) + + self.__entry.set_text( self.__option.get_value() ) #------------------------------------------------------------------------ # @@ -932,10 +1195,27 @@ class GuiMenuOptions: found = True label = True + if isinstance(option, _MenuOptions.PersonOption): widget = GuiPersonOption(option, dialog.dbstate, dialog.uistate, dialog.track, self.__tooltips) + elif isinstance(option, _MenuOptions.FamilyOption): + widget = GuiFamilyOption(option, dialog.dbstate, + dialog.uistate, dialog.track, + self.__tooltips) + elif isinstance(option, _MenuOptions.NoteOption): + widget = GuiNoteOption(option, dialog.dbstate, + dialog.uistate, dialog.track, + self.__tooltips) + elif isinstance(option, _MenuOptions.MediaOption): + widget = GuiMediaOption(option, dialog.dbstate, + dialog.uistate, dialog.track, + self.__tooltips) + elif isinstance(option, _MenuOptions.PersonListOption): + widget = GuiPersonListOption(option, dialog.dbstate, + dialog.uistate, dialog.track, + self.__tooltips) elif isinstance(option, _MenuOptions.NumberOption): widget = GuiNumberOption(option, dialog.dbstate, dialog.uistate, dialog.track, @@ -945,6 +1225,10 @@ class GuiMenuOptions: dialog.uistate, dialog.track, self.__tooltips) label = False + elif isinstance(option, _MenuOptions.DestinationOption): + widget = GuiDestinationOption(option, dialog.dbstate, + dialog.uistate, dialog.track, + self.__tooltips) elif isinstance(option, _MenuOptions.StringOption): widget = GuiStringOption(option, dialog.dbstate, dialog.uistate, dialog.track, @@ -957,14 +1241,6 @@ class GuiMenuOptions: widget = GuiTextOption(option, dialog.dbstate, dialog.uistate, dialog.track, self.__tooltips) - elif isinstance(option, _MenuOptions.FamilyOption): - widget = GuiFamilyOption(option, dialog.dbstate, - dialog.uistate, dialog.track, - self.__tooltips) - elif isinstance(option, _MenuOptions.PersonListOption): - widget = GuiPersonListOption(option, dialog.dbstate, - dialog.uistate, dialog.track, - self.__tooltips) elif isinstance(option, _MenuOptions.ColourOption): widget = GuiColourOption(option, dialog.dbstate, dialog.uistate, dialog.track, diff --git a/src/PluginUtils/_MenuOptions.py b/src/PluginUtils/_MenuOptions.py index ddbe1c396..6a5f5c6c0 100644 --- a/src/PluginUtils/_MenuOptions.py +++ b/src/PluginUtils/_MenuOptions.py @@ -404,7 +404,7 @@ class FilterOption(EnumeratedListOption): """ Return the currently selected filter object. - @return: A person filter object. + @return: A filter object. """ return self.__filters[self.get_value()] @@ -413,7 +413,7 @@ class FilterOption(EnumeratedListOption): # PersonOption class # #------------------------------------------------------------------------- -class PersonOption(Option): +class PersonOption(StringOption): """ This class describes an option that allows a person from the database to be selected. @@ -423,19 +423,19 @@ class PersonOption(Option): @param label: A friendly label to be applied to this option. Example: "Center Person" @type label: string - @param value: A default Gramps ID of a person for this option. + @param value: A Gramps ID of a person for this option. Example: "p11" @type value: string @return: nothing """ - Option.__init__(self, label, "") + StringOption.__init__(self, label, "") #------------------------------------------------------------------------- # # FamilyOption class # #------------------------------------------------------------------------- -class FamilyOption(Option): +class FamilyOption(StringOption): """ This class describes an option that allows a family from the database to be selected. @@ -445,14 +445,57 @@ class FamilyOption(Option): @param label: A friendly label to be applied to this option. Example: "Center Family" @type label: string - @param value: A default Gramps ID of a family for this option. + @param value: A Gramps ID of a family for this option. Example: "f11" @type value: string - @param dbstate: The database state for the database to be used.. - @type value: DbState @return: nothing """ - Option.__init__(self, label, "") + StringOption.__init__(self, label, "") + +#------------------------------------------------------------------------- +# +# NoteOption class +# +#------------------------------------------------------------------------- +class NoteOption(StringOption): + """ + This class describes an option that allows a note from the + database to be selected. + """ + def __init__(self, label): + """ + @param label: A friendly label to be applied to this option. + Example: "Title Note" + @type label: string + @param value: A Gramps ID of a note for this option. + Example: "n11" + @type value: string + @return: nothing + """ + StringOption.__init__(self, label, "") + +#------------------------------------------------------------------------- +# +# MediaOption class +# +#------------------------------------------------------------------------- +class MediaOption(StringOption): + """ + This class describes an option that allows a media object from the + database to be selected. + """ + def __init__(self, label): + """ + @param label: A friendly label to be applied to this option. + Example: "Image" + @type label: string + @param value: A Gramps ID of a media object for this option. + Example: "m11" + @type value: string + @return: nothing + """ + StringOption.__init__(self, label, "") + #------------------------------------------------------------------------- # # PersonListOption class @@ -498,6 +541,69 @@ class SurnameColourOption(Option): """ Option.__init__(self, label, "") +#------------------------------------------------------------------------- +# +# DestinationOption class +# +#------------------------------------------------------------------------- +class DestinationOption(StringOption): + """ + This class describes an option that specifies a destination file or path. + The destination can be a directory or a file. If the destination is a file, + the extension can be specified. + """ + + __signals__ = { 'options-changed' : None } + + def __init__(self, label, value): + """ + @param label: A friendly label to be applied to this option. + Example: "File Name" + @type label: string + @param value: A default destination for this option. + Example: "/home/username/Desktop/" + Example: "/home/username/Desktop/report.pdf" + @type value: string + @param is_directory: Specifies whether the destination is a directory + or a file. + @type value: bool + @return: nothing + """ + StringOption.__init__(self, label, value) + self.__is_directory = False + self.__extension = "" + + def set_directory_entry(self, is_directory): + """ + @param is_directory: Specifies whether the destination is a directory + or a file. + @type value: bool + @return: nothing + """ + self.__is_directory = is_directory + self.emit('options-changed') + + def get_directory_entry(self): + """ + @return: True if the destination is a directory. False if the + destination is a file. + """ + return self.__is_directory + + def set_extension(self, extension): + """ + @param extension: Specifies the extension for the destination file. + @type value: str + @return: nothing + """ + self.__extension = extension + + def get_extension(self): + """ + @return: The extension for the destination file. + """ + return self.__extension + #------------------------------------------------------------------------- # # Menu class diff --git a/src/PluginUtils/__init__.py b/src/PluginUtils/__init__.py index 7897fc321..c485a4b06 100644 --- a/src/PluginUtils/__init__.py +++ b/src/PluginUtils/__init__.py @@ -31,7 +31,8 @@ from _MenuOptions import (NumberOption, BooleanOption, TextOption, EnumeratedListOption, FilterOption, StringOption, ColourOption, PersonOption, PersonListOption, - SurnameColourOption, FamilyOption) + SurnameColourOption, FamilyOption, DestinationOption, + NoteOption, MediaOption) from _GuiOptions import GuiMenuOptions from _PluginMgr import (register_export, register_import, register_tool, register_report, register_relcalc, relationship_class, diff --git a/src/ReportBase/Makefile.am b/src/ReportBase/Makefile.am index ff9c489da..82a67b861 100644 --- a/src/ReportBase/Makefile.am +++ b/src/ReportBase/Makefile.am @@ -25,7 +25,8 @@ pkgdata_PYTHON = \ _StyleEditor.py\ _TemplateParser.py\ _TextFormatComboBox.py\ - _TextReportDialog.py + _TextReportDialog.py\ + _WebReportDialog.py pkgpyexecdir = @pkgpyexecdir@/ReportBase pkgpythondir = @pkgpythondir@/ReportBase diff --git a/src/ReportBase/_BareReportDialog.py b/src/ReportBase/_BareReportDialog.py index e88843469..24eb8641f 100644 --- a/src/ReportBase/_BareReportDialog.py +++ b/src/ReportBase/_BareReportDialog.py @@ -303,6 +303,13 @@ class BareReportDialog(ManagedWindow.ManagedWindow): and to read in any user defined styles for this report. It the builds a menu of all the available styles for the user to choose from.""" + # Build the default style set for this report. + self.default_style = BaseDoc.StyleSheet() + self.options.make_default_style(self.default_style) + + if self.default_style.is_empty(): + # Don't display the option of no styles are used + return # Styles Frame label = gtk.Label("%s:" % _("Style")) @@ -319,10 +326,6 @@ class BareReportDialog(ManagedWindow.ManagedWindow): xoptions=gtk.SHRINK|gtk.FILL,yoptions=gtk.SHRINK) self.col += 1 - # Build the default style set for this report. - self.default_style = BaseDoc.StyleSheet() - self.options.make_default_style(self.default_style) - # Build the initial list of available styles sets. This # includes the default style set and any style sets saved from # previous invocations of gramps. @@ -437,8 +440,9 @@ class BareReportDialog(ManagedWindow.ManagedWindow): retrieves a value whether or not the menu is displayed on the screen. The subclass will know whether this menu was enabled. This is for simplicity of programming.""" - (style_name,self.selected_style) = self.style_menu.get_value() - self.options.handler.set_default_stylesheet_name(style_name) + if not self.default_style.is_empty(): + (style_name, self.selected_style) = self.style_menu.get_value() + self.options.handler.set_default_stylesheet_name(style_name) #------------------------------------------------------------------------ # diff --git a/src/ReportBase/_ReportDialog.py b/src/ReportBase/_ReportDialog.py index d805ad5f0..f2d3bf2c4 100644 --- a/src/ReportBase/_ReportDialog.py +++ b/src/ReportBase/_ReportDialog.py @@ -291,7 +291,10 @@ def report(dbstate,uistate,person,report_class,options_class, elif category == CATEGORY_GRAPHVIZ: from _GraphvizReportDialog import GraphvizReportDialog dialog_class = GraphvizReportDialog - elif category in (CATEGORY_BOOK,CATEGORY_CODE,CATEGORY_VIEW,CATEGORY_WEB): + elif category == CATEGORY_WEB: + from _WebReportDialog import WebReportDialog + dialog_class = WebReportDialog + elif category in (CATEGORY_BOOK,CATEGORY_CODE,CATEGORY_VIEW): try: report_class(dbstate,uistate,person) except Errors.WindowActiveError: diff --git a/src/ReportBase/_ReportOptions.py b/src/ReportBase/_ReportOptions.py index 507d51aa3..aa06eb88b 100644 --- a/src/ReportBase/_ReportOptions.py +++ b/src/ReportBase/_ReportOptions.py @@ -533,6 +533,26 @@ class OptionParser(_Options.OptionParser): else: # Tag is not report-specific, so we let the base class handle it. _Options.OptionParser.endElement(self,tag) + +#------------------------------------------------------------------------ +# +# Empty class to keep the BaseDoc-targeted format happy +# Yes, this is a hack. Find some other way to pass around documents so that +# we don't have to handle them for reports that don't use documents (web) +# +#------------------------------------------------------------------------ +class EmptyDoc: + def init(self): + pass + + def set_creator(self, creator): + pass + + def open(self, filename): + pass + + def close(self): + pass #------------------------------------------------------------------------- # @@ -557,7 +577,7 @@ class OptionHandler(_Options.OptionHandler): """ # These are needed for running reports. # We will not need to save/retreive them, just keep around. - self.doc = None + self.doc = EmptyDoc() # Nasty hack. Text reports replace this self.output = None # Retrieve our options from whole collection diff --git a/src/ReportBase/_WebReportDialog.py b/src/ReportBase/_WebReportDialog.py new file mode 100644 index 000000000..01f430706 --- /dev/null +++ b/src/ReportBase/_WebReportDialog.py @@ -0,0 +1,55 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2008 Brian G. Matherly +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# $Id:$ + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +from _ReportDialog import ReportDialog +from ReportBase import CATEGORY_WEB + +#------------------------------------------------------------------------- +# +# WebReportDialog class +# +#------------------------------------------------------------------------- +class WebReportDialog(ReportDialog): + """ + The WebReportDialog base class. This is a base class for generating + dialogs for web page reports. + """ + + def __init__(self, dbstate, uistate, person, + option_class, name, trans_name): + """Initialize a dialog""" + self.category = CATEGORY_WEB + ReportDialog.__init__(self, dbstate, uistate, person, option_class, + name, trans_name) + + def setup_target_frame(self): + """Target frame is not used.""" + pass + + def parse_target_frame(self): + """Target frame is not used.""" + return 1 \ No newline at end of file diff --git a/src/plugins/BookReport.py b/src/plugins/BookReport.py index 016276ac8..abe701c88 100644 --- a/src/plugins/BookReport.py +++ b/src/plugins/BookReport.py @@ -76,7 +76,7 @@ import ManagedWindow # Import from specific modules in ReportBase from ReportBase._Constants import CATEGORY_BOOK, MODE_GUI, MODE_CLI from ReportBase._BookFormatComboBox import BookFormatComboBox -from ReportBase._BareReportDialog import BareReportDialog +from ReportBase._ReportDialog import ReportDialog from ReportBase._DocReportDialog import DocReportDialog from ReportBase._CommandLineReport import CommandLineReport from ReportBase._ReportOptions import ReportOptions @@ -809,7 +809,7 @@ class BookReportSelector(ManagedWindow.ManagedWindow): self.bk_model.clear() for saved_item in book.get_item_list(): name = saved_item.get_name() - item = BookItem(self.dbase, name) + item = BookItem(self.db, name) item.option_class = saved_item.option_class _initialize_options(item.option_class, self.dbstate) item.set_style_name(saved_item.get_style_name()) @@ -1025,7 +1025,7 @@ class BookReportSelector(ManagedWindow.ManagedWindow): # Book Item Options dialog # #------------------------------------------------------------------------ -class BookItemDialog(BareReportDialog): +class BookItemDialog(ReportDialog): """ This class overrides the interface methods common for different reports @@ -1037,7 +1037,7 @@ class BookItemDialog(BareReportDialog): self.database = dbstate.db self.option_class = option_class - BareReportDialog.__init__(self, dbstate, uistate, None, + ReportDialog.__init__(self, dbstate, uistate, None, option_class, name, translated_name, track) def on_ok_clicked(self, obj): diff --git a/src/plugins/NarrativeWeb.py b/src/plugins/NarrativeWeb.py index f599996c1..bd20abfb2 100644 --- a/src/plugins/NarrativeWeb.py +++ b/src/plugins/NarrativeWeb.py @@ -52,14 +52,6 @@ from unicodedata import normalize import logging log = logging.getLogger(".WebPage") -#------------------------------------------------------------------------ -# -# GNOME/gtk -# -#------------------------------------------------------------------------ -import gtk -import gobject - #------------------------------------------------------------------------ # # GRAMPS module @@ -68,20 +60,17 @@ import gobject import gen.lib import const from GrampsCfg import get_researcher -from Filters import GenericFilter, Rules import Sort from PluginUtils import register_report -from ReportBase import Report, ReportUtils, ReportOptions, \ +from PluginUtils import FilterOption, EnumeratedListOption, PersonOption, \ + BooleanOption, NumberOption, StringOption, DestinationOption, NoteOption, \ + MediaOption +from ReportBase import Report, ReportUtils, MenuReportOptions, \ CATEGORY_WEB, MODE_GUI, MODE_CLI from ReportBase import Bibliography -from ReportBase._ReportDialog import ReportDialog -from ReportBase._CommandLineReport import CommandLineReport -import Errors import Utils import ThumbNails import ImgManip -import GrampsLocale -import GrampsWidgets import Mime from QuestionDialog import ErrorDialog, WarningDialog from BasicUtils import name_displayer as _nd @@ -99,16 +88,16 @@ from gen.lib.eventroletype import EventRoleType _NARRATIVE = "narrative.css" _NAME_COL = 3 -MAX_IMG_WIDTH=800 # resize images that are wider than this -MAX_IMG_HEIGHT=600 # resize images that are taller than this -WIDTH=160 -HEIGHT=50 -VGAP=10 -HGAP=30 -SHADOW=5 -XOFFSET=5 +_MAX_IMG_WIDTH = 800 # resize images that are wider than this +_MAX_IMG_HEIGHT = 600 # resize images that are taller than this +_WIDTH = 160 +_HEIGHT = 50 +_VGAP = 10 +_HGAP = 30 +_SHADOW = 5 +_XOFFSET = 5 -_css_files = [ +_CSS_FILES = [ [_("Modern"), 'main1.css'], [_("Business"), 'main2.css'], [_("Certificate"), 'main3.css'], @@ -118,7 +107,7 @@ _css_files = [ [_("No style sheet"), ''], ] -_character_sets = [ +_CHARACTER_SETS = [ [_('Unicode (recommended)'), 'utf-8'], ['ISO-8859-1', 'iso-8859-1' ], ['ISO-8859-2', 'iso-8859-2' ], @@ -136,15 +125,49 @@ _character_sets = [ ['koi8_r', 'koi8_r', ], ] -_cc = [ - 'Creative Commons License - By attribution', - 'Creative Commons License - By attribution, No derivations', - 'Creative Commons License - By attribution, Share-alike', - 'Creative Commons License - By attribution, Non-commercial', - 'Creative Commons License - By attribution, Non-commercial, No derivations', - 'Creative Commons License - By attribution, Non-commerical, Share-alike', +_CC = [ + '' + 'Creative Commons License - By attribution', + + '' + 'Creative Commons License - By attribution, No derivations', + + '' + 'Creative Commons License - By attribution, Share-alike', + + '' + 'Creative Commons License - By attribution, Non-commercial', + + '' + 'Creative Commons License - By attribution, Non-commercial, No '
+    'derivations', + + '' + 'Creative Commons License - By attribution, Non-commerical, '
+    'Share-alike' ] +_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'), + ] + + wrapper = TextWrapper() wrapper.break_log_words = True wrapper.width = 20 @@ -153,33 +176,33 @@ class BasePage: def __init__(self, title, options, archive, photo_list, gid): self.title_str = title self.gid = gid - self.inc_download = options.handler.options_dict['NWEBdownload'] - self.html_dir = options.handler.options_dict['NWEBod'] - self.copyright = options.handler.options_dict['NWEBcopyright'] + self.inc_download = options['incdownload'] + self.html_dir = options['target'] + self.copyright = options['cright'] self.options = options self.archive = archive - self.ext = options.handler.options_dict['NWEBext'] - self.encoding = options.handler.options_dict['NWEBencoding'] - self.css = options.handler.options_dict['NWEBcss'] - self.noid = options.handler.options_dict['NWEBnoid'] - self.linkhome = options.handler.options_dict['NWEBlinkhome'] - self.showbirth = options.handler.options_dict['NWEBshowbirth'] - self.showdeath = options.handler.options_dict['NWEBshowdeath'] - self.showspouse = options.handler.options_dict['NWEBshowspouse'] - self.showparents = options.handler.options_dict['NWEBshowparents'] - self.showhalfsiblings = options.handler.options_dict['NWEBshowhalfsiblings'] - self.use_intro = options.handler.options_dict['NWEBintronote'] != u""\ - or options.handler.options_dict['NWEBintropic'] != u"" - self.use_contact = options.handler.options_dict['NWEBcontact'] != u""\ - or options.handler.options_dict['NWEBcontactpic'] != u"" - self.use_gallery = options.handler.options_dict['NWEBgallery'] - self.header = options.handler.options_dict['NWEBheader'] - self.footer = options.handler.options_dict['NWEBfooter'] + self.ext = options['ext'] + self.encoding = options['encoding'] + self.css = options['css'] + self.noid = options['nogid'] + self.linkhome = options['linkhome'] + self.showbirth = options['showbirth'] + self.showdeath = options['showdeath'] + self.showspouse = options['showspouse'] + self.showparents = options['showparents'] + self.showhalfsiblings = options['showhalfsiblings'] + self.use_intro = options['intronote'] != u""\ + or options['introimg'] != u"" + self.use_contact = options['contactnote'] != u""\ + or options['contactimg'] != u"" + self.use_gallery = options['gallery'] + self.header = options['headernote'] + self.footer = options['footernote'] self.photo_list = photo_list - self.usegraph = options.handler.options_dict['NWEBgraph'] - self.graphgens = options.handler.options_dict['NWEBgraphgens'] - self.use_home = self.options.handler.options_dict['NWEBhomenote'] != "" or \ - self.options.handler.options_dict['NWEBhomepic'] != "" + self.usegraph = options['graph'] + self.graphgens = options['graphgens'] + self.use_home = self.options['homenote'] != "" or \ + self.options['homeimg'] != "" self.page_title = "" self.warn_dir = True @@ -285,7 +308,7 @@ class BasePage: of.write('
%s\n' % cright) elif self.copyright <=6: of.write('\n') if self.footer: - note = db.get_note_from_handle(self.footer) + note = db.get_note_from_gramps_id(self.footer) of.write('\n') @@ -329,7 +352,7 @@ class BasePage: of.write('\n') of.write('\n') if self.header: - note = db.get_note_from_handle(self.header) + note = db.get_note_from_gramps_id(self.header) of.write('
\n') of.write(note.get(markup=True)) of.write('
\n') @@ -1111,9 +1134,9 @@ class MediaPage(BasePage): # is displayed directly (width, height) = ImgManip.image_size(photo.get_path()) scale = 1.0 - if width > MAX_IMG_WIDTH or height > MAX_IMG_HEIGHT: + if width > _MAX_IMG_WIDTH or height > _MAX_IMG_HEIGHT: # image is too large -- scale it down and link to the full image - scale = min(float(MAX_IMG_WIDTH)/float(width), float(MAX_IMG_HEIGHT)/float(height)) + scale = min(float(_MAX_IMG_WIDTH)/float(width), float(_MAX_IMG_HEIGHT)/float(height)) width = int(width * scale) height = int(height * scale) of.write('\n' % newpath) @@ -1343,8 +1366,8 @@ class IntroductionPage(BasePage): def __init__(self, db, title, options, archive, media_list): BasePage.__init__(self, title, options, archive, media_list, "") - note_id = options.handler.options_dict['NWEBintronote'] - pic_id = options.handler.options_dict['NWEBintropic'] + note_id = options['intronote'] + pic_id = options['introimg'] if self.use_home: of = self.create_file("introduction") @@ -1357,7 +1380,7 @@ class IntroductionPage(BasePage): of.write('

%s

\n' % _('Introduction')) if pic_id: - obj = db.get_object_from_handle(pic_id) + obj = db.get_object_from_gramps_id(pic_id) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): try: @@ -1372,7 +1395,7 @@ class IntroductionPage(BasePage): except (IOError, OSError), msg: WarningDialog(_("Could not add photo to page"), str(msg)) if note_id: - note_obj = db.get_note_from_handle(note_id) + note_obj = db.get_note_from_gramps_id(note_id) text = note_obj.get(markup=True) if note_obj.get_format(): of.write('
\n%s\n
\n' % text) @@ -1394,8 +1417,8 @@ class HomePage(BasePage): def __init__(self, db, title, options, archive, media_list): BasePage.__init__(self, title, options, archive, media_list, "") - note_id = options.handler.options_dict['NWEBhomenote'] - pic_id = options.handler.options_dict['NWEBhomepic'] + note_id = options['homenote'] + pic_id = options['homeimg'] of = self.create_file("index") author = get_researcher().get_name() self.display_header(of,db,_('Home'),author) @@ -1403,7 +1426,7 @@ class HomePage(BasePage): of.write('

%s

\n' % _('Home')) if pic_id: - obj = db.get_object_from_handle(pic_id) + obj = db.get_object_from_gramps_id(pic_id) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): @@ -1420,7 +1443,7 @@ class HomePage(BasePage): WarningDialog(_("Could not add photo to page"), str(msg)) if note_id: - note_obj = db.get_note_from_handle(note_id) + note_obj = db.get_note_from_gramps_id(note_id) text = note_obj.get(markup=True) if note_obj.get_format(): of.write('
\n%s\n
\n' % text) @@ -1610,10 +1633,10 @@ class ContactPage(BasePage): of.write('
\n') of.write('

%s

\n' % _('Contact')) - note_id = options.handler.options_dict['NWEBcontact'] - pic_id = options.handler.options_dict['NWEBcontactpic'] + note_id = options['contactnote'] + pic_id = options['contactimg'] if pic_id: - obj = db.get_object_from_handle(pic_id) + obj = db.get_object_from_gramps_id(pic_id) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): @@ -1652,7 +1675,7 @@ class ContactPage(BasePage): of.write('
\n') if note_id: - note_obj = db.get_note_from_handle(note_id) + note_obj = db.get_note_from_gramps_id(note_id) text = note_obj.get(markup=True) if note_obj.get_format(): text = u"
%s
" % text @@ -1743,8 +1766,8 @@ class IndividualPage(BasePage): of.write('
\n') def draw_box(self,of,center,col,person): - top = center - HEIGHT/2 - xoff = XOFFSET+col*(WIDTH+HGAP) + top = center - _HEIGHT/2 + xoff = _XOFFSET+col*(_WIDTH+_HGAP) of.write('
\n' % (top,xoff+1)) of.write('
') @@ -1758,14 +1781,14 @@ class IndividualPage(BasePage): of.write(_nd.display(person)) of.write('
\n') of.write('
\n') - of.write('
\n' % (top+SHADOW,xoff+SHADOW)) + of.write('
\n' % (top+_SHADOW,xoff+_SHADOW)) of.write('
\n' % (top-1, xoff)) def extend_line(self,of,y0,x0): of.write('
\n' % - (y0,x0,HGAP/2)) + (y0,x0,_HGAP/2)) of.write('
\n' % - (y0+SHADOW,x0,HGAP/2+SHADOW)) + (y0+_SHADOW,x0,_HGAP/2+_SHADOW)) def connect_line(self,of,y0,y1,col): if y0 < y1: @@ -1773,15 +1796,15 @@ class IndividualPage(BasePage): else: y = y1 - x0 = XOFFSET + col * WIDTH + (col-1)*HGAP + HGAP/2 + x0 = _XOFFSET + col * _WIDTH + (col-1)*_HGAP + _HGAP/2 of.write('
\n' % - (y1,x0,HGAP/2)) + (y1,x0,_HGAP/2)) of.write('
\n' % - (y1+SHADOW,x0+SHADOW,HGAP/2+SHADOW)) + (y1+_SHADOW,x0+_SHADOW,_HGAP/2+_SHADOW)) of.write('
\n' % (y,x0,abs(y0-y1))) of.write('
\n' % - (y+SHADOW,x0+SHADOW,abs(y0-y1))) + (y+_SHADOW,x0+_SHADOW,abs(y0-y1))) def draw_connected_box(self,of,center1,center2,col,handle): if not handle: @@ -1802,14 +1825,14 @@ class IndividualPage(BasePage): generations = self.graphgens max_in_col = 1 <<(generations-1) - max_size = HEIGHT*max_in_col + VGAP*(max_in_col+1) + max_size = _HEIGHT*max_in_col + _VGAP*(max_in_col+1) center = int(max_size/2) self.draw_tree(of,1,generations,max_size,0,center,self.person.handle) of.write('\n') of.write('\n') of.write('
\n' % - (max_size,XOFFSET+(generations)*WIDTH+(generations-1)*HGAP)) + (max_size,_XOFFSET+(generations)*_WIDTH+(generations-1)*_HGAP)) def draw_tree(self,of,gen,maxgen,max_size,old_center,new_center,phandle): if gen > maxgen: @@ -1829,7 +1852,7 @@ class IndividualPage(BasePage): family_handle = person.get_main_parents_family_handle() if family_handle: - line_offset = XOFFSET + (gen)*WIDTH + (gen-1)*HGAP + line_offset = _XOFFSET + (gen)*_WIDTH + (gen-1)*_HGAP self.extend_line(of,new_center,line_offset) gen = gen + 1 @@ -2324,11 +2347,11 @@ class IndividualPage(BasePage): #------------------------------------------------------------------------ # -# WebReport +# NavWebReport # #------------------------------------------------------------------------ -class WebReport(Report): - def __init__(self,database,person,options): +class NavWebReport(Report): + def __init__(self, database, person, options): """ Creates WebReport object that produces the report. @@ -2336,40 +2359,23 @@ class WebReport(Report): database - the GRAMPS database instance person - currently selected person - options - instance of the Options class for this report - - This report needs the following parameters (class variables) - that come in the options class. - - filter - od - NWEBlivinginfo - NWEByearsafterdeath - NWEBincpriv - NWEBnonames - NWEBidxcol - NWEBincid - NWEBext - NWEBencoding - NWEBintronote - NWEBhomenote - NWEBhomepic - NWEBnoid - NWEBlinkhome - NWEBshowbirth - NWEBshowdeath - NWEBshowspouse - NWEBshowparents - NWEBshowhalfsiblings + options - instance of the Options class for this report """ + Report.__init__(self, database, person, options) + menu = options.menu + self.opts = {} - if not options.handler.options_dict['NWEBincpriv']: + for optname in menu.get_all_option_names(): + menuopt = menu.get_option_by_name(optname) + self.opts[optname] = menuopt.get_value() + + if not self.opts['incpriv']: self.database = PrivateProxyDb(database) else: self.database = database - livinginfo = options.handler.options_dict['NWEBlivinginfo'] - yearsafterdeath = options.handler.options_dict['NWEByearsafterdeath'] + livinginfo = self.opts['living'] + yearsafterdeath = self.opts['yearsafterdeath'] if livinginfo == LivingProxyDb.MODE_EXCLUDE: self.database = LivingProxyDb(self.database, @@ -2381,39 +2387,33 @@ class WebReport(Report): LivingProxyDb.MODE_RESTRICT, None, yearsafterdeath) - - self.start_person = person - self.options = options - filter_num = options.handler.options_dict['NWEBfilter'] - filters = ReportUtils.get_person_filters(person,include_single=False) - self.filter = filters[filter_num] + filters_option = menu.get_option_by_name('filter') + self.filter = filters_option.get_filter() - self.target_path = options.handler.options_dict['NWEBod'] - self.copyright = options.handler.options_dict['NWEBcopyright'] - self.ext = options.handler.options_dict['NWEBext'] - self.encoding = options.handler.options_dict['NWEBencoding'] - self.css = options.handler.options_dict['NWEBcss'] - self.noid = options.handler.options_dict['NWEBnoid'] - self.linkhome = options.handler.options_dict['NWEBlinkhome'] - self.showbirth = options.handler.options_dict['NWEBshowbirth'] - self.showdeath = options.handler.options_dict['NWEBshowdeath'] - self.showspouse = options.handler.options_dict['NWEBshowspouse'] - self.showparents = options.handler.options_dict['NWEBshowparents'] - self.showhalfsiblings = options.handler.options_dict['NWEBshowhalfsiblings'] - self.title = options.handler.options_dict['NWEBtitle'] + self.target_path = self.opts['target'] + self.copyright = self.opts['cright'] + self.ext = self.opts['ext'] + self.encoding = self.opts['encoding'] + self.css = self.opts['css'] + self.noid = self.opts['nogid'] + self.linkhome = self.opts['linkhome'] + self.showbirth = self.opts['showbirth'] + self.showdeath = self.opts['showdeath'] + self.showspouse = self.opts['showspouse'] + self.showparents = self.opts['showparents'] + self.showhalfsiblings = self.opts['showhalfsiblings'] + self.title = self.opts['title'] self.sort = Sort.Sort(self.database) - self.inc_gallery = options.handler.options_dict['NWEBgallery'] - self.inc_contact = options.handler.options_dict['NWEBcontact'] != u""\ - or options.handler.options_dict['NWEBcontactpic'] != u"" - self.inc_download = options.handler.options_dict['NWEBdownload'] - #self.user_header = options.handler.options_dict['NWEBheader'] - #self.user_footer = options.handler.options_dict['NWEBfooter'] - self.use_archive = options.handler.options_dict['NWEBarchive'] - self.use_intro = options.handler.options_dict['NWEBintronote'] != u""\ - or options.handler.options_dict['NWEBintropic'] != u"" - self.use_home = options.handler.options_dict['NWEBhomenote'] != u"" or\ - options.handler.options_dict['NWEBhomepic'] != u"" + self.inc_gallery = self.opts['gallery'] + self.inc_contact = self.opts['contactnote'] != u""\ + or self.opts['contactimg'] != u"" + self.inc_download = self.opts['incdownload'] + self.use_archive = self.opts['archive'] + self.use_intro = self.opts['intronote'] != u""\ + or self.opts['introimg'] != u"" + self.use_home = self.opts['homenote'] != u"" or\ + self.opts['homeimg'] != u"" def write_report(self): if not self.use_archive: @@ -2535,7 +2535,7 @@ class WebReport(Report): IndividualListPage( self.database, self.title, ind_list, - self.options, archive, self.photo_list) + self.opts, archive, self.photo_list) for person_handle in ind_list: self.progress.step() @@ -2543,7 +2543,7 @@ class WebReport(Report): IndividualPage( self.database, person, self.title, ind_list, - place_list, source_list, self.options, archive, self.photo_list) + place_list, source_list, self.opts, archive, self.photo_list) def surname_pages(self, ind_list, archive): """ @@ -2560,16 +2560,16 @@ class WebReport(Report): defname="index" SurnameListPage( - self.database, self.title, ind_list, self.options, archive, + self.database, self.title, ind_list, self.opts, archive, self.photo_list, SurnameListPage.ORDER_BY_NAME,defname) SurnameListPage( - self.database, self.title, ind_list, self.options, archive, + self.database, self.title, ind_list, self.opts, archive, self.photo_list, SurnameListPage.ORDER_BY_COUNT,"surnames_count") for (surname,handle_list) in local_list: SurnamePage(self.database, surname, handle_list, - self.options, archive, self.photo_list) + self.opts, archive, self.photo_list) self.progress.step() def source_pages(self, source_list, photo_list, archive): @@ -2577,11 +2577,11 @@ class WebReport(Report): self.progress.set_pass(_("Creating source pages"),len(source_list)) SourcesPage(self.database,self.title, source_list.keys(), - self.options, archive, photo_list) + self.opts, archive, photo_list) for key in list(source_list): SourcePage(self.database, self.title, key, source_list, - self.options, archive, photo_list) + self.opts, archive, photo_list) self.progress.step() @@ -2590,13 +2590,13 @@ class WebReport(Report): self.progress.set_pass(_("Creating place pages"),len(place_list)) PlaceListPage( - self.database, self.title, place_list, source_list, self.options, + self.database, self.title, place_list, source_list, self.opts, archive, self.photo_list) for place in place_list.keys(): PlacePage( self.database, self.title, place, source_list, place_list, - self.options, archive, self.photo_list) + self.opts, archive, self.photo_list) self.progress.step() def gallery_pages(self, photo_list, source_list, archive): @@ -2604,7 +2604,7 @@ class WebReport(Report): self.progress.set_pass(_("Creating media pages"),len(photo_list)) GalleryPage(self.database, self.title, source_list, - self.options, archive, self.photo_list) + self.opts, archive, self.photo_list) prev = None total = len(self.photo_list) @@ -2620,7 +2620,7 @@ class WebReport(Report): else: next = photo_keys[index] MediaPage(self.database, self.title, photo_handle, source_list, - self.options, archive, self.photo_list[photo_handle], + self.opts, archive, self.photo_list[photo_handle], (prev, next, index, total)) self.progress.step() prev = photo_handle @@ -2629,16 +2629,18 @@ class WebReport(Report): def base_pages(self, photo_list, archive): if self.use_home: - HomePage(self.database, self.title, self.options, archive, photo_list) + HomePage(self.database, self.title, self.opts, archive, photo_list) if self.inc_contact: - ContactPage(self.database, self.title, self.options, archive, photo_list) + ContactPage(self.database, self.title, self.opts, + archive, photo_list) if self.inc_download: - DownloadPage(self.database, self.title, self.options, archive, photo_list) + DownloadPage(self.database, self.title, self.opts, + archive, photo_list) if self.use_intro: - IntroductionPage(self.database, self.title, self.options, + IntroductionPage(self.database, self.title, self.opts, archive, photo_list) def store_file(self,archive,html_dir,from_path,to_path): @@ -2650,514 +2652,286 @@ class WebReport(Report): else: shutil.copyfile(from_path,os.path.join(html_dir,to_path)) - def add_styles(self,doc): - pass - #------------------------------------------------------------------------ # -# +# NavWebOptions # #------------------------------------------------------------------------ -class WebReportOptions(ReportOptions): - +class NavWebOptions(MenuReportOptions): """ Defines options and provides handling interface. """ + __INCLUDE_LIVING_VALUE = 99 # Arbitrary number - def __init__(self,name,database=None,person_id=None): - ReportOptions.__init__(self,name,person_id) - self.db = database - - # Options specific for this report - self.options_dict = { - 'NWEBfilter' : 0, - 'NWEBarchive' : 0, - 'NWEBgraph' : 1, - 'NWEBgraphgens' : 4, - 'NWEBod' : os.path.join(const.USER_HOME,"NWEB"), - 'NWEBcopyright' : 0, - 'NWEBlivinginfo' : 2, - 'NWEByearsafterdeath' : 30, - 'NWEBincpriv' : 0, - 'NWEBnonames' : 0, - 'NWEBnoid' : 0, - 'NWEBlinkhome' : 0, - 'NWEBshowbirth' : 1, - 'NWEBshowdeath' : 0, - 'NWEBshowspouse' : 0, - 'NWEBshowparents' : 0, - 'NWEBshowhalfsiblings' : 0, - 'NWEBcontact' : '', - 'NWEBcontactpic' : '', - 'NWEBgallery' : 1, - 'NWEBheader' : '', - 'NWEBfooter' : '', - 'NWEBdownload' : 0, - 'NWEBtitle' : _('My Family Tree'), - 'NWEBincid' : 0, - 'NWEBext' : 'html', - 'NWEBencoding' : 'utf-8', - 'NWEBcss' : 'main0.css', - 'NWEBintronote' : '', - 'NWEBintropic' : '', - 'NWEBhomenote' : '', - 'NWEBhomepic' : '', - } - - self.options_help = { - } - - def add_user_options(self, dialog): - priv_msg = _("Do not include records marked private") - living_msg = _("Living People") - death_msg = _("Years from death to consider living") - title_msg = _("Web site title") - ext_msg = _("File extension") - contact_msg = _("Publisher contact note") - contactpic_msg = _("Publisher contact image") - gallery_msg = _("Include images and media objects") - download_msg = _("Include download page") - graph_msg = _("Include ancestor graph") + def __init__(self, name, dbase, person_id=None): + self.__db = dbase + self.__archive = None + self.__target = None + self.__pid = None + self.__filter = None + self.__graph = None + self.__graphgens = None + self.__living = None + self.__yearsafterdeath = None + MenuReportOptions.__init__(self, name, person_id) - filter_index = self.options_dict['NWEBfilter'] - filter_list = ReportUtils.get_person_filters(dialog.person, - include_single=False) - self.filter_menu = gtk.combo_box_new_text() - for filter in filter_list: - #cut name filter so as not to make dialog too large - if len(filter.get_name()) > 60: - self.filter_menu.append_text(filter.get_name()[:60]+'...') - else: - self.filter_menu.append_text(filter.get_name()) - if filter_index > len(filter_list): - filter_index = 0 - self.filter_menu.set_active(filter_index) - dialog.add_option(_('Filter'),self.filter_menu) - - self.no_private = gtk.CheckButton(priv_msg) - self.no_private.set_active(not self.options_dict['NWEBincpriv']) - - self.inc_graph = gtk.CheckButton(graph_msg) - self.inc_graph.set_active(self.options_dict['NWEBgraph']) + def add_menu_options(self, menu): + """ + Add options to the menu for the web calendar. + """ + self.__add_report_options(menu) + self.__add_page_generation_options(menu) + self.__add_privacy_options(menu) + self.__add_advanced_options(menu) - self.graph_gens = gtk.combo_box_new_text() - self.graph_gens_options = ['2','3','4','5'] - for text in self.graph_gens_options: - self.graph_gens.append_text(text) - def_gens = str(self.options_dict['NWEBgraphgens']) - if def_gens in self.graph_gens_options: - self.graph_gens.set_active(self.graph_gens_options.index(def_gens)) + def __add_report_options(self, menu): + """ + Options on the "Report Options" tab. + """ + category_name = _("Report Options") + + self.__archive = BooleanOption(_('Store web pages in .tar.gz archive'), + False) + self.__archive.set_help(_('Whether to store the web pages in an ' + 'archive file')) + menu.add_option(category_name, 'archive', self.__archive) + self.__archive.connect('value-changed', self.__archive_changed) + + self.__target = DestinationOption(_("Destination"), + os.path.join(const.USER_HOME,"NAVWEB")) + self.__target.set_help( _("The destination directory for the web " + "files")) + menu.add_option(category_name, "target", self.__target) + + self.__archive_changed() + + self.__filter = FilterOption(_("Filter"), 0) + self.__filter.set_help( + _("Select filter to restrict people that appear on calendar")) + menu.add_option(category_name, "filter", self.__filter) + self.__filter.connect('value-changed', self.__filter_changed) + + self.__pid = PersonOption(_("Filter Person")) + self.__pid.set_help(_("The center person for the filter")) + menu.add_option(category_name, "pid", self.__pid) + self.__pid.connect('value-changed', self.__update_filters) + + self.__update_filters() + + title = StringOption(_("Web site title"), _('My Family Tree')) + title.set_help(_("The of the web site")) + menu.add_option(category_name, "title", title) + + ext = EnumeratedListOption(_("File extension"), ".html" ) + for etype in ['.html', '.htm', '.shtml', '.php', '.php3', '.cgi']: + ext.add_item(etype, etype) + ext.set_help( _("The extension to be used for the web files")) + menu.add_option(category_name, "ext", ext) + + cright = EnumeratedListOption(_('Copyright'), 0 ) + index = 0 + for copt in _COPY_OPTIONS: + cright.add_item(index, copt) + index += 1 + cright.set_help( _("The copyright to be used for the web files")) + menu.add_option(category_name, "cright", cright) + + encoding = EnumeratedListOption(_('Character set encoding'), 'utf-8' ) + for eopt in _CHARACTER_SETS: + encoding.add_item(eopt[1], eopt[0]) + encoding.set_help( _("The encoding to be used for the web files")) + menu.add_option(category_name, "encoding", encoding) + + css = EnumeratedListOption(_('Stylesheet'), 'main1.css' ) + for style in _CSS_FILES: + css.add_item(style[1], style[0]) + css.set_help( _("The style sheet to be used for the web page")) + menu.add_option(category_name, "css", css) + + self.__graph = BooleanOption(_("Include ancestor graph"), True) + self.__graph.set_help(_('Whether to include an ancestor graph ' + 'on each individual page')) + menu.add_option(category_name, 'graph', self.__graph) + self.__graph.connect('value-changed', self.__graph_changed) + + self.__graphgens = EnumeratedListOption(_('Graph generations'), 4) + self.__graphgens.add_item(2, "2") + self.__graphgens.add_item(3, "3") + self.__graphgens.add_item(4, "4") + self.__graphgens.add_item(5, "5") + self.__graphgens.set_help( _("The number of generations to include in " + "the ancestor graph")) + menu.add_option(category_name, "graphgens", self.__graphgens) + + self.__graph_changed() + + def __add_page_generation_options(self, menu): + """ + Options on the "Page Generation" tab. + """ + category_name = _("Page Generation") + + homenote = NoteOption(_('Home page note')) + homenote.set_help( _("A note to be used on the home page")) + menu.add_option(category_name, "homenote", homenote) + + homeimg = MediaOption(_('Home page image')) + homeimg.set_help( _("An image to be used on the home page")) + menu.add_option(category_name, "homeimg", homeimg) + + intronote = NoteOption(_('Introduction note')) + intronote.set_help( _("A note to be used as the introduction")) + menu.add_option(category_name, "intronote", intronote) + + introimg = MediaOption(_('Introduction image')) + introimg.set_help( _("An image to be used as the introduction")) + menu.add_option(category_name, "introimg", introimg) + + contactnote = NoteOption(_("Publisher contact note")) + contactnote.set_help( _("A note to be used as the publisher contact")) + menu.add_option(category_name, "contactnote", contactnote) + + contactimg = MediaOption(_("Publisher contact image")) + contactimg.set_help( _("An image to be used as the publisher contact")) + menu.add_option(category_name, "contactimg", contactimg) + + headernote = NoteOption(_('HTML user header')) + headernote.set_help( _("A note to be used as the page header")) + menu.add_option(category_name, "headernote", headernote) + + footernote = NoteOption(_('HTML user footer')) + footernote.set_help( _("A note to be used as the page footer")) + menu.add_option(category_name, "footernote", footernote) + + gallery = BooleanOption(_("Include images and media objects"), True) + gallery.set_help(_('Whether to include a gallery of media objects')) + menu.add_option(category_name, 'gallery', gallery) + + incdownload = BooleanOption(_("Include download page"), False) + incdownload.set_help(_('Whether to include a database download option')) + menu.add_option(category_name, 'incdownload', incdownload) + + nogid = BooleanOption(_('Suppress GRAMPS ID'), False) + nogid.set_help(_('Whether to include the Gramps ID of objects')) + menu.add_option(category_name, 'nogid', nogid) + + def __add_privacy_options(self, menu): + """ + Options on the "Privacy" tab. + """ + category_name = _("Privacy") + + incpriv = BooleanOption(_("Include records marked private"), False) + incpriv.set_help(_('Whether to include private objects')) + menu.add_option(category_name, 'incpriv', incpriv) + + self.__living = EnumeratedListOption(_("Living People"), + self.__INCLUDE_LIVING_VALUE ) + self.__living.add_item(LivingProxyDb.MODE_EXCLUDE, _("Exclude")) + self.__living.add_item(LivingProxyDb.MODE_RESTRICT, _("Restrict")) + self.__living.add_item(self.__INCLUDE_LIVING_VALUE, _("Include")) + self.__living.set_help(_("How to handle living people")) + menu.add_option(category_name, "living", self.__living) + self.__living.connect('value-changed', self.__living_changed) + + self.__yearsafterdeath = NumberOption(_("Years from death to consider " + "living"), 30, 0, 100) + self.__yearsafterdeath.set_help(_("This allows you to restrict " + "information on people who have not " + "been dead for very long")) + menu.add_option(category_name, 'yearsafterdeath', + self.__yearsafterdeath) + + self.__living_changed() + + def __add_advanced_options(self, menu): + """ + Options on the "Advanced" tab. + """ + category_name = _("Advanced") + + linkhome = BooleanOption(_('Include link to home person on every ' + 'page'), False) + linkhome.set_help(_('Whether to include a link to the home person')) + menu.add_option(category_name, 'linkhome', linkhome) + + showbirth = BooleanOption(_("Include a column for birth dates on the " + "index pages"), True) + showbirth.set_help(_('Whether to include a birth column')) + menu.add_option(category_name, 'showbirth', showbirth) + + showdeath = BooleanOption(_("Include a column for death dates on the " + "index pages"), False) + showdeath.set_help(_('Whether to include a death column')) + menu.add_option(category_name, 'showdeath', showdeath) + + showspouse = BooleanOption(_("Include a column for partners on the " + "index pages"), False) + showspouse.set_help(_('Whether to include a partners column')) + menu.add_option(category_name, 'showspouse', showspouse) + + showparents = BooleanOption(_("Include a column for parents on the " + "index pages"), False) + showparents.set_help(_('Whether to include a parents column')) + menu.add_option(category_name, 'showparents', showparents) + + showhalfsiblings = BooleanOption(_("Include a column for half-siblings" + " on the index pages"), False) + showhalfsiblings.set_help(_("Whether to include a half-siblings " + "column")) + menu.add_option(category_name, 'showhalfsiblings', showhalfsiblings) + + def __archive_changed(self): + """ + Update the change of storage: archive or directory + """ + if self.__archive.get_value() == True: + self.__target.set_extension(".tar.gz") + self.__target.set_directory_entry(False) else: - self.graph_gens.set_active(0) + self.__target.set_directory_entry(True) - self.noid = gtk.CheckButton(_('Suppress GRAMPS ID')) - self.noid.set_active(self.options_dict['NWEBnoid']) - - self.include_gallery = gtk.CheckButton(gallery_msg) - self.include_gallery.set_active(self.options_dict['NWEBgallery']) - - self.living = gtk.combo_box_new_text() - self.living.append_text(_("Exclude")) - self.living.append_text(_("Restrict")) - self.living.append_text(_("Include")) - self.living.set_active(self.options_dict['NWEBlivinginfo']) + def __update_filters(self): + """ + Update the filter list based on the selected person + """ + gid = self.__pid.get_value() + person = self.__db.get_person_from_gramps_id(gid) + filter_list = ReportUtils.get_person_filters(person, False) + self.__filter.set_filters(filter_list) - self.restrict_years = gtk.SpinButton(gtk.Adjustment(1,0,100,1)) - self.restrict_years.set_value(self.options_dict['NWEByearsafterdeath']) - - self.inc_download = gtk.CheckButton(download_msg) - self.inc_download.set_active(self.options_dict['NWEBdownload']) - - self.linkhome = gtk.CheckButton(_('Include link to home person on every page')) - self.linkhome.set_active(self.options_dict['NWEBlinkhome']) - - self.showbirth = gtk.CheckButton(_('Include a column for birth dates on the index pages')) - self.showbirth.set_active(self.options_dict['NWEBshowbirth']) - - self.showdeath = gtk.CheckButton(_('Include a column for death dates on the index pages')) - self.showdeath.set_active(self.options_dict['NWEBshowdeath']) - - self.showspouse = gtk.CheckButton(_('Include a column for partners on the index pages')) - self.showspouse.set_active(self.options_dict['NWEBshowspouse']) - - self.showparents = gtk.CheckButton(_('Include a column for parents on the index pages')) - self.showparents.set_active(self.options_dict['NWEBshowparents']) - - self.showhalfsiblings = gtk.CheckButton(_('Include half-brothers and half-sisters as siblings')) - self.showhalfsiblings.set_active(self.options_dict['NWEBshowhalfsiblings']) - - # FIXME: document this: - # 0 -- no images of any kind - # 1 -- no living images, but some images - # 2 -- any images - - self.title = gtk.Entry() - self.title.set_text(self.options_dict['NWEBtitle']) - - self.ext = gtk.combo_box_new_text() - self.ext_options = ['.html','.htm','.shtml','.php','.php3','.cgi'] - for text in self.ext_options: - self.ext.append_text(text) - - self.copy = gtk.combo_box_new_text() - self.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'), - ] - for text in self.copy_options: - self.copy.append_text(text) - - def_ext = "." + self.options_dict['NWEBext'] - self.ext.set_active(self.ext_options.index(def_ext)) - - index = self.options_dict['NWEBcopyright'] - self.copy.set_active(index) - - cset_node = None - cset = self.options_dict['NWEBencoding'] - - store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - for data in _character_sets: - if data[1] == cset: - cset_node = store.append(row=data) - else: - store.append(row=data) - self.encoding = GrampsNoteComboBox(store,cset_node) - - cset_node = None - cset = self.options_dict['NWEBcss'] - store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - for data in _css_files: - if data[1] == cset: - cset_node = store.append(row=data) - else: - store.append(row=data) - self.css = GrampsNoteComboBox(store,cset_node) - - dialog.add_option(title_msg,self.title) - dialog.add_option(ext_msg,self.ext) - dialog.add_option(_('Character set encoding'),self.encoding) - dialog.add_option(_('Stylesheet'),self.css) - dialog.add_option(_('Copyright'),self.copy) - dialog.add_option(_('Ancestor graph generations'),self.graph_gens) - dialog.add_option(None,self.inc_graph) - - title = _("Page Generation") - - self.home_nt_box, self.home_nt_label, self.home_nt_share_btn \ - = mk_object_entry() - self.home_note = GrampsWidgets.NoteEntry(dialog.dbstate, - dialog.uistate, dialog.track, - self.home_nt_label, - self.set_home_nt_val, self.get_home_nt_val, - None, self.home_nt_share_btn) - self.home_pic_box, self.home_pic_label, self.home_pic_share_btn \ - = mk_object_entry() - self.home_pic = GrampsWidgets.MediaEntry(dialog.dbstate, - dialog.uistate, dialog.track, - self.home_pic_label, - self.set_home_pic_val, self.get_home_pic_val, - None, self.home_pic_share_btn) - self.intro_nt_box, self.intro_nt_label, self.intro_nt_share_btn \ - = mk_object_entry() - self.intro_note = GrampsWidgets.NoteEntry(dialog.dbstate, - dialog.uistate, dialog.track, - self.intro_nt_label, - self.set_intro_nt_val, self.get_intro_nt_val, - None, self.intro_nt_share_btn) - self.intro_pic_box, self.intro_pic_label, self.intro_pic_share_btn \ - = mk_object_entry() - self.intro_pic = GrampsWidgets.MediaEntry(dialog.dbstate, - dialog.uistate, dialog.track, - self.intro_pic_label, - self.set_intro_pic_val, self.get_intro_pic_val, - None, self.intro_pic_share_btn) - self.contact_nt_box, self.contact_nt_label, self.contact_nt_share_btn \ - = mk_object_entry() - self.contact = GrampsWidgets.NoteEntry(dialog.dbstate, - dialog.uistate, dialog.track, - self.contact_nt_label, - self.set_contact_nt_val, self.get_contact_nt_val, - None, self.contact_nt_share_btn) - self.contact_pic_box, self.contact_pic_label, \ - self.contact_pic_share_btn = mk_object_entry() - self.contact_pic = GrampsWidgets.MediaEntry(dialog.dbstate, - dialog.uistate, dialog.track, - self.contact_pic_label, - self.set_contact_pic_val, self.get_contact_pic_val, - None, self.contact_pic_share_btn) - self.header_nt_box, self.header_nt_label, self.header_nt_share_btn \ - = mk_object_entry() - self.header = GrampsWidgets.NoteEntry(dialog.dbstate, - dialog.uistate, dialog.track, - self.header_nt_label, - self.set_header_nt_val, self.get_header_nt_val, - None, self.header_nt_share_btn) - self.footer_nt_box, self.footer_nt_label, self.footer_nt_share_btn \ - = mk_object_entry() - self.footer = GrampsWidgets.NoteEntry(dialog.dbstate, - dialog.uistate, dialog.track, - self.footer_nt_label, - self.set_footer_nt_val, self.get_footer_nt_val, - None, self.footer_nt_share_btn) - - dialog.add_frame_option(title,_('Home Page note'), - self.home_nt_box) - dialog.add_frame_option(title,_('Home Page image'), - self.home_pic_box) - dialog.add_frame_option(title,_('Introduction Note'), - self.intro_nt_box) - dialog.add_frame_option(title,_('Introduction image'), - self.intro_pic_box) - dialog.add_frame_option(title, contact_msg, self.contact_nt_box) - dialog.add_frame_option(title, contactpic_msg, self.contact_pic_box) - dialog.add_frame_option(title, _('HTML user header'), - self.header_nt_box) - dialog.add_frame_option(title, _('HTML user footer'), - self.footer_nt_box) - dialog.add_frame_option(title, '', self.include_gallery) - dialog.add_frame_option(title, None, self.inc_download) - dialog.add_frame_option(title, None, self.noid) - - title = _("Privacy") - dialog.add_frame_option(title,None,self.no_private) - dialog.add_frame_option(title,living_msg,self.living) - dialog.add_frame_option(title,death_msg,self.restrict_years) - - title = _("Advanced Options") - dialog.add_frame_option(title,None,self.linkhome,) - dialog.add_frame_option(title,None,self.showbirth) - dialog.add_frame_option(title,None,self.showdeath) - dialog.add_frame_option(title,None,self.showspouse) - dialog.add_frame_option(title,None,self.showparents) - dialog.add_frame_option(title,None,self.showhalfsiblings) - - def set_nt_val(self, opt, val): - ''' store the note handle in options - ''' - if val is None: - self.options_dict[opt] = u'' + def __filter_changed(self): + """ + Handle filter change. If the filter is not specific to a person, + disable the person option + """ + filter_value = self.__filter.get_value() + if filter_value in [1, 2, 3, 4]: + # Filters 1, 2, 3 and 4 rely on the center person + self.__pid.set_available(True) else: - self.options_dict[opt] = unicode(val) - - def get_nt_val(self, opt): - ''' obtain note handle - ''' - val = self.options_dict[opt] - if val == "": - return None - else: - return val - - def set_home_nt_val(self, val): - self.set_nt_val('NWEBhomenote', val) - - def get_home_nt_val(self): - return self.get_nt_val('NWEBhomenote') - - def set_home_pic_val(self, val): - self.set_nt_val('NWEBhomepic', val) - - def get_home_pic_val(self): - return self.get_nt_val('NWEBhomepic') - - def set_intro_nt_val(self, val): - self.set_nt_val('NWEBintronote', val) - - def get_intro_nt_val(self): - return self.get_nt_val('NWEBintronote') - - def set_intro_pic_val(self, val): - self.set_nt_val('NWEBintropic', val) - - def get_intro_pic_val(self): - return self.get_nt_val('NWEBintropic') - - def set_contact_nt_val(self, val): - self.set_nt_val('NWEBcontact', val) - - def get_contact_nt_val(self): - return self.get_nt_val('NWEBcontact') - - def set_contact_pic_val(self, val): - self.set_nt_val('NWEBcontactpic', val) - - def get_contact_pic_val(self): - return self.get_nt_val('NWEBcontactpic') - - def set_header_nt_val(self, val): - self.set_nt_val('NWEBheader', val) - - def get_header_nt_val(self): - return self.get_nt_val('NWEBheader') - - def set_footer_nt_val(self, val): - self.set_nt_val('NWEBfooter', val) - - def get_footer_nt_val(self): - return self.get_nt_val('NWEBfooter') - - def parse_user_options(self, dialog): - """Parse the privacy options frame of the dialog. Save the - user selected choices for later use.""" + # The rest don't + self.__pid.set_available(False) + + def __graph_changed(self): + """ + Handle enabling or disabling the ancestor graph + """ + self.__graphgens.set_available(self.__graph.get_value()) - self.options_dict['NWEBfilter'] = int(self.filter_menu.get_active()) - self.options_dict['NWEBlivinginfo'] = int(self.living.get_active()) - self.options_dict['NWEByearsafterdeath'] = \ - int(self.restrict_years.get_text()) - self.options_dict['NWEBincpriv'] = int(not self.no_private.get_active()) - self.options_dict['NWEBnoid'] = int(self.noid.get_active()) - self.options_dict['NWEBlinkhome'] = int(self.linkhome.get_active()) - self.options_dict['NWEBshowbirth'] = int(self.showbirth.get_active()) - self.options_dict['NWEBshowdeath'] = int(self.showdeath.get_active()) - self.options_dict['NWEBshowspouse'] = int(self.showspouse.get_active()) - self.options_dict['NWEBshowparents'] = int(self.showparents.get_active()) - self.options_dict['NWEBshowhalfsiblings'] = int(self.showhalfsiblings.get_active()) - self.options_dict['NWEBgallery'] = int(self.include_gallery.get_active()) - self.options_dict['NWEBdownload'] = int(self.inc_download.get_active()) - self.options_dict['NWEBtitle'] = unicode(self.title.get_text()) - self.options_dict['NWEBgraph'] = int(self.inc_graph.get_active()) - - index = self.graph_gens.get_active() - generations = 4 - if index >= 0: - generations = int(self.graph_gens_options[index]) - self.options_dict['NWEBgraphgens'] = generations - - index = self.ext.get_active() - if index >= 0: - html_ext = self.ext_options[index] + def __living_changed(self): + """ + Handle a change in the living option + """ + if self.__living.get_value() == self.__INCLUDE_LIVING_VALUE: + self.__yearsafterdeath.set_available(False) else: - html_ext = "html" - if html_ext[0] == '.': - html_ext = html_ext[1:] - self.options_dict['NWEBext'] = html_ext + self.__yearsafterdeath.set_available(True) - self.options_dict['NWEBencoding'] = self.encoding.get_handle() - self.options_dict['NWEBcss'] = self.css.get_handle() - self.options_dict['NWEBod'] = dialog.target_path - self.options_dict['NWEBcopyright'] = self.copy.get_active() - - #------------------------------------------------------------------------ - # - # Callback functions from the dialog - # - #------------------------------------------------------------------------ - def make_default_style(self,default_style): + def make_default_style(self, default_style): """Make the default output style for the Web Pages Report.""" pass -#------------------------------------------------------------------------ -# -# -# -#------------------------------------------------------------------------ -class WebReportDialog(ReportDialog): - - HELP_TOPIC = "rep-web" - - def __init__(self, dbstate, uistate, person): - self.database = dbstate.db - self.person = person - name = "navwebpage" - translated_name = _("Generate Web Site") - self.options = WebReportOptions(name,self.database) - self.category = CATEGORY_WEB - ReportDialog.__init__(self, dbstate, uistate, person, self.options, - name, translated_name) - self.style_name = None - - self.modal_call(self.make_report) - - def on_cancel(self, *obj): - self.close(*obj) - - def setup_style_frame(self): - """The style frame is not used in this dialog.""" - pass - - def parse_style_frame(self): - """The style frame is not used in this dialog.""" - self.options.handler.options_dict['NWEBarchive'] = int( - self.archive.get_active()) - - def setup_report_options_frame(self): - self.archive = gtk.CheckButton(_('Store web pages in .tar.gz archive')) - self.archive.set_alignment(0.0,0.5) - self.archive.set_active( - self.options.handler.options_dict['NWEBarchive']) - self.archive.connect('toggled',self.archive_toggle) - self.add_option(None,self.archive) - ReportDialog.setup_report_options_frame(self) - - def archive_toggle(self,obj): - if obj.get_active(): - # The .tar.gz box is on - # Set doc label, mark file vs dir, add '.tar.gz' to the path - self.target_fileentry.set_directory_entry(False) - self.doc_label.set_label("%s:" % _("Filename")) - fname = self.target_fileentry.get_full_path(0) - if fname[-7:] != '.tar.gz': - fname = fname + '.tar.gz' - self.target_fileentry.set_filename(fname) - else: - # The .tar.gz box is off - # Set doc label, mark dir vs file, remove '.tar.gz' from path - self.target_fileentry.set_directory_entry(True) - self.doc_label.set_label("%s:" % _("Directory")) - fname = self.target_fileentry.get_full_path(0) - if fname[-7:] == '.tar.gz': - fname = fname[:-7] - self.target_fileentry.set_filename(fname) - - def get_title(self): - """The window title for this dialog""" - return "%s - %s - GRAMPS" % (_("Generate Web Site"),_("Web Page")) - - def get_target_browser_title(self): - """The title of the window created when the 'browse' button is - clicked in the 'Save As' frame.""" - return _("Target Directory") - - def get_target_is_directory(self): - """This report creates a directory full of files, not a single file.""" - return 1 - - def get_default_directory(self): - """Get the name of the directory to which the target dialog - box should default. This value can be set in the preferences - panel.""" - return self.options.handler.options_dict['NWEBod'] - - def make_document(self): - """Do Nothing. This document will be created in the - make_report routine.""" - pass - - def setup_format_frame(self): - """Do nothing, since we don't want a format frame (NWEB only)""" - pass - - def parse_format_frame(self): - """The format frame is not used in this dialog.""" - pass - - def make_report(self): - """Create the object that will produce the web pages.""" - - try: - MyReport = WebReport(self.database,self.person, - self.options) - MyReport.write_report() - except Errors.FilterError, msg: - (m1,m2) = msg.messages() - ErrorDialog(m1,m2) def sort_people(db,handle_list): flist = set(handle_list) @@ -3191,87 +2965,6 @@ def sort_people(db,handle_list): sorted_lists.append((name,entries)) return sorted_lists -#------------------------------------------------------------------------ -# -# -# -#------------------------------------------------------------------------ -def cl_report(database,name,category,options_str_dict): - - clr = CommandLineReport(database,name,category,WebReportOptions, - options_str_dict) - - # Exit here if show option was given - if clr.show: - return - - MyReport = WebReport(database,clr.person,clr.option_class) - MyReport.write_report() - -#------------------------------------------------------------------------ -# -# Empty class to keep the BaseDoc-targeted format happy -# -#------------------------------------------------------------------------ -class EmptyDoc: - def __init__(self,styles,type,template,orientation,source=None): - pass - - def init(self): - pass - - -#------------------------------------------------------------------------- -# -# GrampsNoteComboBox -# -#------------------------------------------------------------------------- -class GrampsNoteComboBox(gtk.ComboBox): - """ - Derived from the ComboBox, this widget provides handling of Report - Styles. - """ - - def __init__(self,model=None,node=None): - """ - Initializes the combobox, building the display column. - """ - gtk.ComboBox.__init__(self,model) - cell = gtk.CellRendererText() - self.pack_start(cell,True) - self.add_attribute(cell,'text',0) - if node: - self.set_active_iter(node) - else: - self.set_active(0) - self.local_store = model - - def get_handle(self): - """ - Returns the selected key (style sheet name). - - @returns: Returns the name of the selected style sheet - @rtype: str - """ - active = self.get_active_iter() - handle = u"" - if active: - handle = self.local_store.get_value(active,1) - return handle - -def mk_object_entry(): - ''' return a vbox widget with fields for object selection - ''' - box = gtk.HBox() - label = gtk.Label() - label.set_justify(gtk.JUSTIFY_LEFT) - labelexpand = gtk.Label() - button_sel = gtk.Button() - box.pack_start(label, expand=False, fill=True) - box.pack_start(labelexpand, expand=True, fill=True) - box.pack_start(button_sel, expand=False, fill=False) - return (box, label, button_sel) - #------------------------------------------------------------------------- # # @@ -3280,12 +2973,13 @@ def mk_object_entry(): register_report( name = 'navwebpage', category = CATEGORY_WEB, - report_class = WebReportDialog, - options_class = cl_report, + report_class = NavWebReport, + options_class = NavWebOptions, modes = MODE_GUI | MODE_CLI, translated_name = _("Narrated Web Site..."), status = _("Stable"), - author_name="Donald N. Allingham", - author_email="don@gramps-project.org", - description=_("Generates web (HTML) pages for individuals, or a set of individuals."), + author_name = "Donald N. Allingham", + author_email = "don@gramps-project.org", + description = _("Generates web (HTML) pages for individuals, or a set of " + "individuals."), ) diff --git a/src/plugins/WebCal.py b/src/plugins/WebCal.py index 3b2a86757..bba69514f 100644 --- a/src/plugins/WebCal.py +++ b/src/plugins/WebCal.py @@ -1,8 +1,8 @@ # # Gramps - a GTK+/GNOME based genealogy program # -# Copyright (C) 2007 Thom Sturgill -# Copyright (C) 2007 Brian G. Matherly +# 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 @@ -58,14 +58,6 @@ except: import logging log = logging.getLogger(".WebPage") -#------------------------------------------------------------------------ -# -# GNOME/gtk -# -#------------------------------------------------------------------------ -import gtk -import gobject - #------------------------------------------------------------------------ # # GRAMPS module @@ -76,10 +68,10 @@ import const import BaseDoc from GrampsCfg import get_researcher from PluginUtils import register_report -from ReportBase import (Report, ReportUtils, ReportOptions, CATEGORY_WEB, +from ReportBase import (Report, ReportUtils, MenuReportOptions, CATEGORY_WEB, MODE_GUI) -from ReportBase._ReportDialog import ReportDialog -import Errors +from PluginUtils import FilterOption, EnumeratedListOption, PersonOption, \ + BooleanOption, NumberOption, StringOption, DestinationOption import Utils import GrampsLocale from QuestionDialog import ErrorDialog @@ -92,7 +84,7 @@ from Utils import probably_alive #------------------------------------------------------------------------ _CALENDAR = "calendar.css" -_character_sets = [ +_CHARACTER_SETS = [ [_('Unicode (recommended)'), 'utf-8'], ['ISO-8859-1', 'iso-8859-1' ], ['ISO-8859-2', 'iso-8859-2' ], @@ -110,15 +102,48 @@ _character_sets = [ ['koi8_r', 'koi8_r', ], ] -_cc = [ - '
Creative Commons License - By attribution', - 'Creative Commons License - By attribution, No derivations', - 'Creative Commons License - By attribution, Share-alike', - 'Creative Commons License - By attribution, Non-commercial', - 'Creative Commons License - By attribution, Non-commercial, No derivations', - 'Creative Commons License - By attribution, Non-commerical, Share-alike', +_CC = [ + '' + 'Creative Commons License - By attribution', + + '' + 'Creative Commons License - By attribution, No derivations', + + '' + 'Creative Commons License - By attribution, Share-alike', + + '' + 'Creative Commons License - By attribution, Non-commercial', + + '' + 'Creative Commons License - By attribution, Non-commercial, No '
+    'derivations', + + '' + 'Creative Commons License - By attribution, Non-commerical, '
+    'Share-alike' ] +_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): """ Returns a Date object of the particular year/month/day. @@ -129,75 +154,52 @@ def make_date(year, month, day): #------------------------------------------------------------------------ # -# WebReport +# WebCalReport # #------------------------------------------------------------------------ -class WebReport(Report): - def __init__(self,database,person,options): - """ - Creates WebReport object that produces the report. - - The arguments are: - - database - the GRAMPS database instance - person - currently selected person - options - instance of the Options class for this report - - This report needs the following parameters (class variables) - that come in the options class. - - filter Surname - od Country - WCext Year - WCencoding Alive - WCod Birthday - WCcopyright Anniv - Month_image Month_repeat - WCtitle - Note_text1 - Note_text2 - Note_text3 - Note_text4 - Note_text5 - Note_text6 - Note_text7 - Note_text8 - Note_text9 - Note_text10 - Note_text11 - Note_text12 - """ +class WebCalReport(Report): + """ + Creates WebCalReport object that produces the report. + """ + def __init__(self, database, person, options): + Report.__init__(self, database, person, options) + menu = options.menu self.database = database - self.start_person = person self.options = options - - filter_num = options.handler.options_dict['WCfilter'] - filters = ReportUtils.get_person_filters(person) - self.filter = filters[filter_num] - - self.ext = options.handler.options_dict['WCext'] - self.html_dir = options.handler.options_dict['WCod'] - self.copy = options.handler.options_dict['WCcopyright'] - self.encoding = options.handler.options_dict['WCencoding'] - self.Title_text = options.handler.options_dict['WCtitle'] - self.Note = [options.handler.options_dict['Note_text1'],options.handler.options_dict['Note_text2'], - options.handler.options_dict['Note_text3'], options.handler.options_dict['Note_text4'], - options.handler.options_dict['Note_text5'], options.handler.options_dict['Note_text6'], - options.handler.options_dict['Note_text7'], options.handler.options_dict['Note_text8'], - options.handler.options_dict['Note_text9'], options.handler.options_dict['Note_text10'], - options.handler.options_dict['Note_text11'],options.handler.options_dict['Note_text12']] - self.Month_image = options.handler.options_dict['Month_image'] - self.Month_repeat = options.handler.options_dict['Month_repeat'] - self.Country = options.handler.options_dict['Country'] - self.Year = options.handler.options_dict['Year'] - self.Surname = options.handler.options_dict['Surname'] - self.Alive = options.handler.options_dict['alive'] - self.Birthday = options.handler.options_dict['birthdays'] - self.Anniv = options.handler.options_dict['anniversaries'] - self.Serif_fonts = options.handler.options_dict['Serif_fonts'] - self.SanSerif_fonts = options.handler.options_dict['SanSerif_fonts'] - self.Home_link = options.handler.options_dict['Home_link'] + + 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): """ Returns person's name, unless maiden_name given, unless married_name listed. """ @@ -410,7 +412,7 @@ class WebReport(Report): of.write('src="http://www.w3.org/Icons/valid-xhtml10" ') of.write('alt="Valid XHTML 1.0 Transitional" height="31" width="88" />

\n') if self.copy > 0 and self.copy <= 6: - text = _cc[self.copy-1] + text = _CC[self.copy-1] from_path = os.path.join(const.IMAGE_DIR,"somerights20.gif") shutil.copyfile(from_path,os.path.join(self.html_dir,"somerights20.gif")) else: @@ -481,7 +483,7 @@ class WebReport(Report): # get the information, first from holidays: if self.Country != 0: # Don't include holidays - self.get_holidays(self.Year, _countries[self.Country]) # _country is currently global + self.get_holidays(self.Year, _COUNTRIES[self.Country]) # _country is currently global # get data from database: self.collect_data() # generate the report: @@ -668,295 +670,228 @@ class WebReport(Report): } self.add_day_item(text, year, month, day) - #------------------------------------------------------------------------ # -# +# WebCalOptions # #------------------------------------------------------------------------ -class WebReportOptions(ReportOptions): - +class WebCalOptions(MenuReportOptions): """ Defines options and provides handling interface. """ + + def __init__(self, name, dbase): + self.__db = dbase + self.__pid = None + self.__filter = None + MenuReportOptions.__init__(self, name, dbase) - def __init__(self,name,database=None,person_id=None): - ReportOptions.__init__(self,name,person_id) - self.db = database - - # Options specific for this report - self.options_dict = { - 'WCfilter' : 0, - 'WCod' : os.path.join(const.USER_HOME,"WEBCAL"), - 'WCcopyright' : 0, - 'WCtitle' : _('My Family Calendar'), - 'WCext' : 'html', - 'WCencoding' : 'utf-8', - 'Month_image' : '', - 'Month_repeat' : 1, - 'Note_text1' : _('This prints in January'), - 'Note_text2' : _('This prints in February'), - 'Note_text3' : _('This prints in March'), - 'Note_text4' : _('This prints in April'), - 'Note_text5' : _('This prints in May'), - 'Note_text6' : _('This prints in June'), - 'Note_text7' : _('This prints in July'), - 'Note_text8' : _('This prints in August'), - 'Note_text9' : _('This prints in September'), - 'Note_text10' : _('This prints in October'), - 'Note_text11' : _('This prints in November'), - 'Note_text12' : _('This prints in December'), - 'Year' : time.localtime()[0], - 'Country' : 0, - 'Surname' : 1, - 'alive' : 1, - 'birthdays' : 1, - 'anniversaries' : 1, - 'SanSerif_fonts' : '"Verdana","Helvetica","Arial",sans-serif', - 'Serif_fonts' : '"Georgia","Times New Roman","Times",serif', - 'Home_link' : '../index.html', - } - - self.options_help = { - } - - def add_user_options(self,dialog): - - ext_msg = _("File extension") - - self.ext = gtk.combo_box_new_text() - self.ext_options = ['.html','.htm','.shtml','.php','.php3','.cgi'] - for text in self.ext_options: - self.ext.append_text(text) - - self.copy = gtk.combo_box_new_text() - self.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'), - ] - for text in self.copy_options: - self.copy.append_text(text) - - def_ext = "." + self.options_dict['WCext'] - self.ext.set_active(self.ext_options.index(def_ext)) - - index = self.options_dict['WCcopyright'] - self.copy.set_active(index) - - cset_node = None - cset = self.options_dict['WCencoding'] - - store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - for data in _character_sets: - if data[1] == cset: - cset_node = store.append(row=data) - else: - store.append(row=data) - self.encoding = GrampsNoteComboBox(store,cset_node) - - dialog.add_option(ext_msg,self.ext) - dialog.add_option(_('Character set encoding'),self.encoding) - dialog.add_option(_('Copyright'),self.copy) - - - title = _("Content Options") - -# year_msg = "Year of calendar" -# country_msg = "Country for holidays" -# surname_msg = "Birthday surname" -# alive_msg = "Only include living people" -# birthday_msg = "Include birthdays" -# anniversary_msg = "Include anniversaries" + def add_menu_options(self, menu): + """ + Add options to the menu for the web calendar. + """ + self.__add_report_options(menu) + self.__add_content_options(menu) + self.__add_misc_options(menu) + self.__add_notes_options(menu) + + def __add_report_options(self, menu): + """ + Options on the "Report Options" tab. + """ + category_name = _("Report Options") - filter_index = self.options_dict['WCfilter'] - filter_list = ReportUtils.get_person_filters(dialog.person) - self.filter_menu = gtk.combo_box_new_text() - for filter in filter_list: - self.filter_menu.append_text(filter.get_name()) - if filter_index > len(filter_list): - filter_index = 0 - self.filter_menu.set_active(filter_index) - - self.year = gtk.SpinButton() - self.year.set_digits(0) - self.year.set_increments(1,2) - self.year.set_range(0,2100) - self.year.set_numeric(True) - self.year.set_value(self.options_dict['Year']) - - self.Country_options = map(lambda c: ("", c, c), _countries) - self.Country = gtk.ComboBox() - store = gtk.ListStore(gobject.TYPE_STRING) - self.Country.set_model(store) - cell = gtk.CellRendererText() - self.Country.pack_start(cell,True) - self.Country.add_attribute(cell,'text',0) - for item in self.Country_options: - store.append(row=[item[2]]) - self.Country.set_active(self.options_dict['Country']) - - self.alive = gtk.CheckButton(_('Check to include ONLY the living')) - self.alive.set_active(self.options_dict['alive']) - - self.surname = gtk.CheckButton(_('Check for wives to use maiden name')) - self.surname.set_active(self.options_dict['Surname']) - - self.birthday = gtk.CheckButton(_('Check to include birthdays')) - self.birthday.set_active(self.options_dict['birthdays']) - - self.anniversary = gtk.CheckButton(_('Check to include anniversaries')) - self.anniversary.set_active(self.options_dict['anniversaries']) - - dialog.add_frame_option(title,_('Filter'),self.filter_menu) - dialog.add_frame_option(title,_('Year of calendar'),self.year) - dialog.add_frame_option(title,_('Country for holidays'),self.Country) - dialog.add_frame_option(title,_('Birthday surname'),self.surname) - dialog.add_frame_option(title,_('Only include living people'),self.alive) - dialog.add_frame_option(title,_('Include birthdays'),self.birthday) - dialog.add_frame_option(title,_('Include anniversaries'),self.anniversary) - - - title = _("Misc Options") - - self.Serif_fonts = gtk.Entry() - self.Serif_fonts.set_text(str(self.options_dict['Serif_fonts'])) - - self.SanSerif_fonts = gtk.Entry() - self.SanSerif_fonts.set_text(str(self.options_dict['SanSerif_fonts'])) - - self.Month_image = gtk.Entry() - self.Month_image.set_text(str(self.options_dict['Month_image'])) - - self.Home_link = gtk.Entry() - self.Home_link.set_text(str(self.options_dict['Home_link'])) - - self.repeat_options = [_('no-repeat'),_('repeat'), - _('repeat-x'),_('repeat-y')] - self.Month_repeat = gtk.combo_box_new_text() - for text in self.repeat_options: - self.Month_repeat.append_text(text) - index = self.options_dict['Month_repeat'] - self.Month_repeat.set_active(index) - - self.Title_text = gtk.Entry() - self.Title_text.set_text(self.options_dict['WCtitle']) - - dialog.add_frame_option(title,_('Calendar Title'),self.Title_text) - dialog.add_frame_option(title,_('Home link'),self.Home_link) - dialog.add_frame_option(title,_('Serif font family'),self.Serif_fonts) - dialog.add_frame_option(title,_('San-Serif font family'),self.SanSerif_fonts) - dialog.add_frame_option(title,_('Background Image'),self.Month_image) - dialog.add_frame_option(title,_('Image Repeat'),self.Month_repeat) - - - title = _("Months 1-6 Notes") - - note_msg = [_('Jan Note'),_('Feb Note'),_('Mar Note'),_('Apr Note'), - _('May Note'),_('Jun Note'),_('Jul Note'),_('Aug Note'), - _('Sep Note'),_('Oct Note'),_('Nov Note'),_('Dec Note')] - - self.Note_text1 = gtk.Entry() - self.Note_text1.set_text(str(self.options_dict['Note_text1'])) - - self.Note_text2 = gtk.Entry() - self.Note_text2.set_text(str(self.options_dict['Note_text2'])) - - self.Note_text3 = gtk.Entry() - self.Note_text3.set_text(str(self.options_dict['Note_text3'])) - - self.Note_text4 = gtk.Entry() - self.Note_text4.set_text(str(self.options_dict['Note_text4'])) - - self.Note_text5 = gtk.Entry() - self.Note_text5.set_text(str(self.options_dict['Note_text5'])) - - self.Note_text6 = gtk.Entry() - self.Note_text6.set_text(str(self.options_dict['Note_text6'])) - - dialog.add_frame_option(title,note_msg[0],self.Note_text1) - dialog.add_frame_option(title,note_msg[1],self.Note_text2) - dialog.add_frame_option(title,note_msg[2],self.Note_text3) - dialog.add_frame_option(title,note_msg[3],self.Note_text4) - dialog.add_frame_option(title,note_msg[4],self.Note_text5) - dialog.add_frame_option(title,note_msg[5],self.Note_text6) - - title = _("Months 7-12 Notes") - - self.Note_text7 = gtk.Entry() - self.Note_text7.set_text(str(self.options_dict['Note_text7'])) - - self.Note_text8 = gtk.Entry() - self.Note_text8.set_text(str(self.options_dict['Note_text8'])) - - self.Note_text9 = gtk.Entry() - self.Note_text9.set_text(str(self.options_dict['Note_text9'])) - - self.Note_text10 = gtk.Entry() - self.Note_text10.set_text(str(self.options_dict['Note_text10'])) - - self.Note_text11 = gtk.Entry() - self.Note_text11.set_text(str(self.options_dict['Note_text11'])) - - self.Note_text12 = gtk.Entry() - self.Note_text12.set_text(str(self.options_dict['Note_text12'])) - - dialog.add_frame_option(title,note_msg[6],self.Note_text7) - dialog.add_frame_option(title,note_msg[7],self.Note_text8) - dialog.add_frame_option(title,note_msg[8],self.Note_text9) - dialog.add_frame_option(title,note_msg[9],self.Note_text10) - dialog.add_frame_option(title,note_msg[10],self.Note_text11) - dialog.add_frame_option(title,note_msg[11],self.Note_text12) - - def parse_user_options(self,dialog): - """ Save the user selected choices for later use.""" + target = DestinationOption( _("Destination"), + os.path.join(const.USER_HOME,"WEBCAL")) + target.set_help( _("The destination directory for the web files")) + target.set_directory_entry(True) + menu.add_option(category_name, "target", target) - index = self.ext.get_active() - if index >= 0: - html_ext = self.ext_options[index] + ext = EnumeratedListOption(_("File extension"), ".html" ) + for etype in ['.html', '.htm', '.shtml', '.php', '.php3', '.cgi']: + ext.add_item(etype, etype) + ext.set_help( _("The extension to be used for the web files")) + menu.add_option(category_name, "ext", ext) + + cright = EnumeratedListOption(_('Copyright'), 0 ) + index = 0 + for copt in _COPY_OPTIONS: + cright.add_item(index, copt) + index += 1 + cright.set_help( _("The copyright to be used for the web files")) + menu.add_option(category_name, "cright", cright) + + encoding = EnumeratedListOption(_('Character set encoding'), 'utf-8' ) + for eopt in _CHARACTER_SETS: + encoding.add_item(eopt[1], eopt[0]) + encoding.set_help( _("The encoding to be used for the web files")) + menu.add_option(category_name, "encoding", encoding) + + def __add_content_options(self, menu): + """ + Options on the "Content Options" tab. + """ + category_name = _("Content Options") + + year = NumberOption(_("Year of calendar"), time.localtime()[0], + 1000, 3000) + year.set_help(_("Year of calendar")) + menu.add_option(category_name, "year", year) + + self.__filter = FilterOption(_("Filter"), 0) + self.__filter.set_help( + _("Select filter to restrict people that appear on calendar")) + menu.add_option(category_name, "filter", self.__filter) + self.__filter.connect('value-changed', self.__filter_changed) + + self.__pid = PersonOption(_("Filter Person")) + self.__pid.set_help(_("The center person for the filter")) + menu.add_option(category_name, "pid", self.__pid) + self.__pid.connect('value-changed', self.__update_filters) + + self.__update_filters() + + country = EnumeratedListOption(_('Country for holidays'), 0 ) + index = 0 + for item in _COUNTRIES: + country.add_item(index, item) + index += 1 + country.set_help( _("Holidays will be included for the selected " + "country")) + menu.add_option(category_name, "country", country) + + alive = BooleanOption(_("Include only living people"), True) + alive.set_help(_("Include only living people in the calendar")) + menu.add_option(category_name, "alive", alive) + + birthdays = BooleanOption(_("Include birthdays"), True) + birthdays.set_help(_("Include birthdays in the calendar")) + menu.add_option(category_name, "birthdays", birthdays) + + anniversaries = BooleanOption(_("Include anniversaries"), True) + anniversaries.set_help(_("Include anniversaries in the calendar")) + menu.add_option(category_name, "anniversaries", anniversaries) + + surname = BooleanOption(_('Check for wives to use maiden name'), True) + surname.set_help(_("Attempt to use maiden names of women")) + menu.add_option(category_name, "surname", surname) + + def __add_misc_options(self, menu): + """ + Options on the "Misc Options" tab. + """ + category_name = _("Misc Options") + + title = StringOption(_('Calendar Title'), _('My Family Calendar')) + title.set_help(_("The title of the calendar")) + menu.add_option(category_name, "title", title) + + home_link = StringOption(_('Home link'), '../index.html') + home_link.set_help(_("The link to be included to direct the user to " + "the main page of the web site")) + menu.add_option(category_name, "home_link", home_link) + + serif_fonts = StringOption(_('Serif font family'), + '"Georgia","Times New Roman","Times",serif') + serif_fonts.set_help(_("Serif font family")) + menu.add_option(category_name, "serif_fonts", serif_fonts) + + sanserif_fonts = StringOption(_('San-Serif font family'), + '"Verdana","Helvetica","Arial",sans-serif') + sanserif_fonts.set_help(_('San-Serif font family')) + menu.add_option(category_name, "sanserif_fonts", sanserif_fonts) + + background = StringOption(_('Background Image'), "") + background.set_help(_('The image to be used as the page background')) + menu.add_option(category_name, "background", background) + + repeat = EnumeratedListOption(_('Image Repeat'), 1 ) + repeat.add_item(0, _('no-repeat')) + repeat.add_item(1, _('repeat')) + repeat.add_item(2, _('repeat-x')) + repeat.add_item(3, _('repeat-y')) + repeat.set_help( _("Whether to repeat the background image")) + menu.add_option(category_name, "repeat", repeat) + + def __add_notes_options(self, menu): + """ + Options on the "Months Notes" tabs. + """ + category_name = _("Months 1-6 Notes") + + note_jan = StringOption(_('Jan Note'), _('This prints in January')) + note_jan.set_help(_("The note for the month of January")) + menu.add_option(category_name, "note_jan", note_jan) + + note_feb = StringOption(_('Feb Note'), _('This prints in February')) + note_feb.set_help(_("The note for the month of February")) + menu.add_option(category_name, "note_feb", note_feb) + + note_mar = StringOption(_('Mar Note'), _('This prints in March')) + note_mar.set_help(_("The note for the month of March")) + menu.add_option(category_name, "note_mar", note_mar) + + note_apr = StringOption(_('Apr Note'), _('This prints in April')) + note_apr.set_help(_("The note for the month of April")) + menu.add_option(category_name, "note_apr", note_apr) + + note_may = StringOption(_('May Note'), _('This prints in May')) + note_may.set_help(_("The note for the month of May")) + menu.add_option(category_name, "note_may", note_may) + + note_jun = StringOption(_('Jun Note'), _('This prints in June')) + note_jun.set_help(_("The note for the month of June")) + menu.add_option(category_name, "note_jun", note_jun) + + category_name = _("Months 7-12 Notes") + + note_jul = StringOption(_('Jul Note'), _('This prints in July')) + note_jul.set_help(_("The note for the month of July")) + menu.add_option(category_name, "note_jul", note_jul) + + note_aug = StringOption(_('Aug Note'), _('This prints in August')) + note_aug.set_help(_("The note for the month of August")) + menu.add_option(category_name, "note_aug", note_aug) + + note_sep = StringOption(_('Sep Note'), _('This prints in September')) + note_sep.set_help(_("The note for the month of September")) + menu.add_option(category_name, "note_sep", note_sep) + + note_oct = StringOption(_('Oct Note'), _('This prints in October')) + note_oct.set_help(_("The note for the month of October")) + menu.add_option(category_name, "note_oct", note_oct) + + note_nov = StringOption(_('Nov Note'), _('This prints in November')) + note_nov.set_help(_("The note for the month of November")) + menu.add_option(category_name, "note_nov", note_nov) + + note_dec = StringOption(_('Dec Note'), _('This prints in December')) + note_dec.set_help(_("The note for the month of December")) + menu.add_option(category_name, "note_dec", note_dec) + + def __update_filters(self): + """ + Update the filter list based on the selected person + """ + gid = self.__pid.get_value() + person = self.__db.get_person_from_gramps_id(gid) + filter_list = ReportUtils.get_person_filters(person, False) + self.__filter.set_filters(filter_list) + + def __filter_changed(self): + """ + Handle filter change. If the filter is not specific to a person, + disable the person option + """ + filter_value = self.__filter.get_value() + if filter_value in [1, 2, 3, 4]: + # Filters 1, 2, 3 and 4 rely on the center person + self.__pid.set_available(True) else: - html_ext = "html" - if html_ext[0] == '.': - html_ext = html_ext[1:] - self.options_dict['WCext'] = html_ext - self.options_dict['WCfilter'] = int(self.filter_menu.get_active()) - self.options_dict['WCencoding'] = self.encoding.get_handle() - self.options_dict['WCod'] = dialog.target_path - self.options_dict['WCcopyright'] = self.copy.get_active() - self.options_dict['WCtitle'] = unicode(self.Title_text.get_text()) - self.options_dict['Note_text1'] = unicode(self.Note_text1.get_text()) - self.options_dict['Note_text2'] = unicode(self.Note_text2.get_text()) - self.options_dict['Note_text3'] = unicode(self.Note_text3.get_text()) - self.options_dict['Note_text4'] = unicode(self.Note_text4.get_text()) - self.options_dict['Note_text5'] = unicode(self.Note_text5.get_text()) - self.options_dict['Note_text6'] = unicode(self.Note_text6.get_text()) - self.options_dict['Note_text7'] = unicode(self.Note_text7.get_text()) - self.options_dict['Note_text8'] = unicode(self.Note_text8.get_text()) - self.options_dict['Note_text9'] = unicode(self.Note_text9.get_text()) - self.options_dict['Note_text10'] = unicode(self.Note_text10.get_text()) - self.options_dict['Note_text11'] = unicode(self.Note_text11.get_text()) - self.options_dict['Note_text12'] = unicode(self.Note_text12.get_text()) - self.options_dict['Year'] = self.year.get_value_as_int() - self.options_dict['Country'] = self.Country.get_active() - self.options_dict['Surname'] = int(self.surname.get_active()) - self.options_dict['alive'] = int(self.alive.get_active()) - self.options_dict['birthdays'] = int(self.birthday.get_active()) - self.options_dict['anniversaries'] = int(self.anniversary.get_active()) - self.options_dict['SanSerif_fonts'] = unicode(self.SanSerif_fonts.get_text()) - self.options_dict['Serif_fonts'] = unicode(self.Serif_fonts.get_text()) - self.options_dict['Home_link'] = unicode(self.Home_link.get_text()) + # The rest don't + self.__pid.set_available(False) - #------------------------------------------------------------------------ - # - # Callback functions from the dialog - # - #------------------------------------------------------------------------ - def make_default_style(self,default_style): + def make_default_style(self, default_style): """Make the default output style for the Web Calendar There are 5 named styles for this report. @@ -966,139 +901,83 @@ class WebReportOptions(ReportOptions): WC-Note - The text placed at the bottom of each calendar. WC-Table - controls the overall appearance of the calendar table. - """ + """ # # WC-Title # font = BaseDoc.FontStyle() - font.set(face=BaseDoc.FONT_SERIF,size=24,bold=1,italic=1,color=(0x80,0x0,0x0)) + font.set(face=BaseDoc.FONT_SERIF, size=24, bold=1, + italic=1, color=(0x80, 0x0, 0x0)) para = BaseDoc.ParagraphStyle() para.set_font(font) - para.set(bgcolor=((0xb0,0xc4,0xde))) + para.set(bgcolor=((0xb0, 0xc4, 0xde))) para.set_alignment(BaseDoc.PARA_ALIGN_CENTER) - para.set_description(_('The style used for the title ("My Family Calendar") of the page. The background color sets the PAGE background. Borders DO NOT work.')) - default_style.add_paragraph_style("WC-Title",para) + para.set_description(_('The style used for the title ("My Family ' + 'Calendar") of the page. The background color ' + 'sets the PAGE background. Borders DO NOT ' + 'work.')) + default_style.add_paragraph_style("WC-Title", para) # # WC-Month # font = BaseDoc.FontStyle() - font.set(face=BaseDoc.FONT_SERIF,size=48,bold=1,italic=1,color=((0x80,0x0,0x0))) + font.set(face=BaseDoc.FONT_SERIF, size=48, bold=1, + italic=1, color=((0x80, 0x0, 0x0))) para = BaseDoc.ParagraphStyle() para.set_font(font) - para.set(bgcolor=((0xf0,0xe6,0x8c))) + para.set(bgcolor=((0xf0, 0xe6, 0x8c))) para.set_alignment(BaseDoc.PARA_ALIGN_CENTER) - para.set_description(_('The style used for the month name and year, it controls the font face, size, style, color and the background color of the block, including the day-name area. Inclusion of a graphic does not cover the day-name area.')) - default_style.add_paragraph_style("WC-Month",para) + para.set_description(_('The style used for the month name and year, it' + ' controls the font face, size, style, color ' + 'and the background color of the block, ' + 'including the day-name area. Inclusion of a ' + 'graphic does not cover the day-name area.')) + default_style.add_paragraph_style("WC-Month", para) # # WC-Text # font = BaseDoc.FontStyle() - font.set(face=BaseDoc.FONT_SERIF,size=16,italic=1,color=((0x80,0x0,0x0))) + font.set(face=BaseDoc.FONT_SERIF, size=16, + italic=1, color=((0x80, 0x0, 0x0))) para = BaseDoc.ParagraphStyle() para.set_font(font) - para.set(bgcolor=((0xf0,0xf8,0xff))) + para.set(bgcolor=((0xf0, 0xf8, 0xff))) para.set_alignment(BaseDoc.PARA_ALIGN_LEFT) - para.set_description(_('The style used for text in the body of the calendar, it controls font size, face, style, color, and alignment. The background color is used ONLY for cells containing text, allowing for high-lighting of dates.')) - default_style.add_paragraph_style("WC-Text",para) + para.set_description(_('The style used for text in the body of the ' + 'calendar, it controls font size, face, style, ' + 'color, and alignment. The background color is ' + 'used ONLY for cells containing text, allowing ' + 'for high-lighting of dates.')) + default_style.add_paragraph_style("WC-Text", para) # # WC-Note # font = BaseDoc.FontStyle() - font.set(face=BaseDoc.FONT_SANS_SERIF,size=16,color=((0x0,0x0,0x0))) + font.set(face=BaseDoc.FONT_SANS_SERIF, size=16, color=((0x0, 0x0, 0x0))) para = BaseDoc.ParagraphStyle() para.set_font(font) - para.set(bgcolor=((0xff,0xff,0xff))) + para.set(bgcolor=((0xff, 0xff, 0xff))) para.set_alignment(BaseDoc.PARA_ALIGN_LEFT) - para.set_description(_('The style used for notes at the bottom of the calendar, it controls font size, face, style, color and positioning. The background color setting affect all EMPTY calendar cells.')) - default_style.add_paragraph_style("WC-Note",para) + para.set_description(_('The style used for notes at the bottom of the ' + 'calendar, it controls font size, face, style, ' + 'color and positioning. The background color ' + 'setting affect all EMPTY calendar cells.')) + default_style.add_paragraph_style("WC-Note", para) # # WC-Table # font = BaseDoc.FontStyle() - font.set(face=BaseDoc.FONT_SERIF,size=24,color=((0x80,0x0,0x0))) + font.set(face=BaseDoc.FONT_SERIF, size=24, color=((0x80, 0x0, 0x0))) para = BaseDoc.ParagraphStyle() para.set_font(font) - para.set(bgcolor=((0xff,0xff,0xff))) + para.set(bgcolor=((0xff, 0xff, 0xff))) para.set_alignment(BaseDoc.PARA_ALIGN_RIGHT) - para.set_description(_('The style used for the table itself. This affects the color of the table lines and the color, font, size, and positioning of the calendar date numbers. It also controls the color of the day names.')) - default_style.add_paragraph_style("WC-Table",para) - -#------------------------------------------------------------------------ -# -# -# -#------------------------------------------------------------------------ -class WebReportDialog(ReportDialog): - - HELP_TOPIC = "rep-web" - - def __init__(self,dbstate,uistate,person): - self.database = dbstate.db - self.person = person - name = "WebCal" - translated_name = _("Generate Web Calendar") - self.options = WebReportOptions(name,self.database) - self.category = CATEGORY_WEB - - ReportDialog.__init__(self,dbstate,uistate,person,self.options, - name,translated_name) - # test - ths - #self.style_name = None - - while True: - response = self.window.run() - if response == gtk.RESPONSE_OK: - self.make_report() - break - elif response != gtk.RESPONSE_HELP: - break - self.close() - - def dummy_toggle(self,obj): - pass - - def get_title(self): - """The window title for this dialog""" - return "%s - GRAMPS" % (_("Generate Web Calendar")) - - def get_target_browser_title(self): - """The title of the window created when the 'browse' button is - clicked in the 'Save As' frame.""" - return _("Target Directory") - - def get_target_is_directory(self): - """This report creates a directory full of files, not a single file.""" - return 1 - - def get_default_directory(self): - """Get the name of the directory to which the target dialog - box should default. This value can be set in the preferences - panel.""" - return self.options.handler.options_dict['WCod'] - - def make_document(self): - """Do Nothing. This document will be created in the - make_report routine.""" - pass - - def setup_format_frame(self): - """Do nothing, since we don't want a format frame """ - pass - - def parse_format_frame(self): - """The format frame is not used in this dialog.""" - self.options.handler.set_format_name("html") - - def make_report(self): - """Create the object that will produce the web pages.""" - - try: - MyReport = WebReport(self.database,self.person, - self.options) - MyReport.write_report() - except Errors.FilterError, msg: - (m1,m2) = msg.messages() - ErrorDialog(m1,m2) + para.set_description(_('The style used for the table itself. This ' + 'affects the color of the table lines and the ' + 'color, font, size, and positioning of the ' + 'calendar date numbers. It also controls the ' + 'color of the day names.')) + default_style.add_paragraph_style("WC-Table", para) #------------------------------------------------------------------------ # @@ -1158,7 +1037,6 @@ class Element: return retval - class Xml2Obj: """ XML to Object """ def __init__(self): @@ -1308,7 +1186,18 @@ class Holidays: retval.append(rule["name"]) return retval -def get_countries(): +def process_holiday_file(filename): + """ This will process a holiday file for country names """ + parser = Xml2Obj() + element = parser.Parse(filename) + country_list = [] + for country_set in element.children: + if country_set.name == "country": + if country_set.attributes["name"] not in country_list: + country_list.append(country_set.attributes["name"]) + return country_list + +def _get_countries(): """ Looks in multiple places for holidays.xml files """ locations = [const.PLUGINS_DIR, const.USER_PLUGINS] holiday_file = 'holidays.xml' @@ -1324,86 +1213,10 @@ def get_countries(): country_list.insert(0, _("Don't include holidays")) return country_list -def process_holiday_file(filename): - """ This will process a holiday file for country names """ - parser = Xml2Obj() - element = parser.Parse(filename) - country_list = [] - for country_set in element.children: - if country_set.name == "country": - if country_set.attributes["name"] not in country_list: - country_list.append(country_set.attributes["name"]) - return country_list +# TODO: Only load this once the first time it is actually needed so Gramps +# doesn't take so long to start up. +_COUNTRIES = _get_countries() -## Currently reads the XML file on load. Could move this someplace else -## so it only loads when needed. - -_countries = get_countries() - -#------------------------------------------------------------------------ -# -# Empty class to keep the BaseDoc-targeted format happy -# -#------------------------------------------------------------------------ -class EmptyDoc: - def __init__(self,styles,type,template,orientation,source=None): - pass - - def init(self): - pass - -#------------------------------------------------------------------------- -# -# GrampsNoteComboBox -# -#------------------------------------------------------------------------- -class GrampsNoteComboBox(gtk.ComboBox): - """ - Derived from the ComboBox, this widget provides handling of Report - Styles. - """ - - def __init__(self,model=None,node=None): - """ - Initializes the combobox, building the display column. - """ - gtk.ComboBox.__init__(self,model) - cell = gtk.CellRendererText() - self.pack_start(cell,True) - self.add_attribute(cell,'text',0) - if node: - self.set_active_iter(node) - else: - self.set_active(0) - self.local_store = model - - def get_handle(self): - """ - Returns the selected key (style sheet name). - - @returns: Returns the name of the selected style sheet - @rtype: str - """ - active = self.get_active_iter() - handle = u"" - if active: - handle = self.local_store.get_value(active,1) - return handle - -def mk_combobox(media_list,select_value): - store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - node = None - - for data in media_list: - if data[1] == select_value: - node = store.append(row=data) - else: - store.append(row=data) - widget = GrampsNoteComboBox(store,node) - if len(media_list) == 0: - widget.set_sensitive(False) - return widget - #------------------------------------------------------------------------- # # @@ -1412,8 +1225,8 @@ def mk_combobox(media_list,select_value): register_report( name = 'WebCal', category = CATEGORY_WEB, - report_class = WebReportDialog, - options_class = WebReportOptions, + report_class = WebCalReport, + options_class = WebCalOptions, modes = MODE_GUI, translated_name = _("Web Calendar..."), status = _("Beta"),