diff --git a/src/gui/plug/_guioptions.py b/src/gui/plug/_guioptions.py index a78b775b7..2291f9b93 100644 --- a/src/gui/plug/_guioptions.py +++ b/src/gui/plug/_guioptions.py @@ -7,7 +7,7 @@ # Copyright (C) 2009 Nick Hall # Copyright (C) 2010 Jakim Friant # Copyright (C) 2011 Adam Stein -# Copyright (C) 2011 Paul Franklin +# Copyright (C) 2011-2012 Paul Franklin # # 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 @@ -163,7 +163,7 @@ class GuiStringOption(gtk.Entry): """ This class displays an option that is a simple one-line string. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): """ @param option: The option to display. @type option: gen.plug.menu.StringOption @@ -225,7 +225,7 @@ class GuiColorOption(gtk.ColorButton): """ This class displays an option that allows the selection of a colour. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): self.__option = option value = self.__option.get_value() gtk.ColorButton.__init__( self, gtk.gdk.color_parse(value) ) @@ -278,7 +278,7 @@ class GuiNumberOption(gtk.SpinButton): This class displays an option that is a simple number with defined maximum and minimum values. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): self.__option = option decimals = 0 @@ -350,7 +350,7 @@ class GuiTextOption(gtk.ScrolledWindow): """ This class displays an option that is a multi-line string. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): self.__option = option gtk.ScrolledWindow.__init__(self) self.set_shadow_type(gtk.SHADOW_IN) @@ -433,7 +433,7 @@ class GuiBooleanOption(gtk.CheckButton): """ This class displays an option that is a boolean (True or False). """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): self.__option = option gtk.CheckButton.__init__(self, self.__option.get_label()) self.set_active(self.__option.get_value()) @@ -489,7 +489,7 @@ class GuiEnumeratedListOption(gtk.HBox): This class displays an option that provides a finite number of values. Each possible value is assigned a value and a description. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): gtk.HBox.__init__(self) evtBox = gtk.EventBox() self.__option = option @@ -582,7 +582,7 @@ class GuiPersonOption(gtk.HBox): This class displays an option that allows a person from the database to be selected. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): """ @param option: The option to display. @type option: gen.plug.menu.PersonOption @@ -612,11 +612,12 @@ class GuiPersonOption(gtk.HBox): person_handle = self.__uistate.get_active('Person') person = self.__dbstate.db.get_person_from_handle(person_handle) - if not person: + if override or not person: # Pick up the stored option value if there is one person = self.__db.get_person_from_gramps_id(gid) if not person: + # If all else fails, get the default person to avoid bad values person = self.__db.get_default_person() if not person: @@ -706,7 +707,7 @@ class GuiFamilyOption(gtk.HBox): This class displays an option that allows a family from the database to be selected. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): """ @param option: The option to display. @type option: gen.plug.menu.FamilyOption @@ -730,7 +731,7 @@ class GuiFamilyOption(gtk.HBox): self.pack_start(pevt, False) self.pack_end(family_button, False) - self.__initialize_family() + self.__initialize_family(override) self.valuekey = self.__option.connect('value-changed', self.__value_changed) @@ -740,10 +741,10 @@ class GuiFamilyOption(gtk.HBox): pevt.set_tooltip_text(self.__option.get_help()) family_button.set_tooltip_text(_('Select a different family')) - def __initialize_family(self): + def __initialize_family(self, override): """ Find a family to initialize the option with. If there is no saved - family option, use the active family. If there ris no active + family option, use the active family. If there is no active family, try to find a family that the user is likely interested in. """ family_list = [] @@ -752,7 +753,7 @@ class GuiFamilyOption(gtk.HBox): # Use the active family if one is selected family = self.__uistate.get_active('Family') - if family: + if family and not override: family_list = [family] else: # Use the stored option value @@ -892,7 +893,7 @@ 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): + def __init__(self, option, dbstate, uistate, track, override): """ @param option: The option to display. @type option: gen.plug.menu.NoteOption @@ -996,7 +997,7 @@ 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): + def __init__(self, option, dbstate, uistate, track, override): """ @param option: The option to display. @type option: gen.plug.menu.MediaOption @@ -1097,7 +1098,7 @@ class GuiPersonListOption(gtk.HBox): This class displays a widget that allows multiple people from the database to be selected. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): """ @param option: The option to display. @type option: gen.plug.menu.PersonListOption @@ -1274,7 +1275,7 @@ class GuiPlaceListOption(gtk.HBox): This class displays a widget that allows multiple places from the database to be selected. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): """ @param option: The option to display. @type option: gen.plug.menu.PlaceListOption @@ -1418,7 +1419,7 @@ class GuiSurnameColorOption(gtk.HBox): selected from the database, and to assign a colour (not necessarily unique) to each one. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): """ @param option: The option to display. @type option: gen.plug.menu.SurnameColorOption @@ -1609,7 +1610,7 @@ class GuiDestinationOption(gtk.HBox): This class displays an option that allows the user to select a DestinationOption. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): """ @param option: The option to display. @type option: gen.plug.menu.DestinationOption @@ -1738,7 +1739,7 @@ class GuiStyleOption(GuiEnumeratedListOption): """ This class displays a StyleOption. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): """ @param option: The option to display. @type option: gen.plug.menu.StyleOption @@ -1778,7 +1779,7 @@ class GuiBooleanListOption(gtk.HBox): This class displays an option that provides a list of check boxes. Each possible value is assigned a value and a description. """ - def __init__(self, option, dbstate, uistate, track): + def __init__(self, option, dbstate, uistate, track, override): gtk.HBox.__init__(self) self.__option = option self.__cbutton = [] @@ -1890,10 +1891,14 @@ _OPTIONS = ( ) del menu -def make_gui_option(option, dbstate, uistate, track): +def make_gui_option(option, dbstate, uistate, track, override=False): """ Stand-alone function so that Options can be used in other ways, too. Takes an Option and returns a GuiOption. + + override: if True will override the GuiOption's normal behavior + (in a GuiOption-dependant fashion, for instance in a GuiPersonOption + it will force the use of the options's value to set the GuiOption) """ label, widget = True, None @@ -1910,7 +1915,7 @@ def make_gui_option(option, dbstate, uistate, track): "can't make GuiOption: unknown option type: '%s'" % option) if widget: - widget = widget(option, dbstate, uistate, track) + widget = widget(option, dbstate, uistate, track, override) return widget, label diff --git a/src/plugins/bookreport.py b/src/plugins/bookreport.py index 630fc6a0a..6f406c267 100644 --- a/src/plugins/bookreport.py +++ b/src/plugins/bookreport.py @@ -4,7 +4,7 @@ # Copyright (C) 2003-2007 Donald N. Allingham # Copyright (C) 2007-2008 Brian G. Matherly # Copyright (C) 2010 Jakim Friant -# Copyright (C) 2011 Paul Franklin +# Copyright (C) 2011-2012 Paul Franklin # # 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 @@ -80,6 +80,8 @@ from gui.managedwindow import ManagedWindow, set_titles from gui.glade import Glade import gui.utils import gui.user +from gui.plug import make_gui_option +from types import ClassType # Import from specific modules in ReportBase from gen.plug.report import CATEGORY_BOOK, book_categories @@ -447,7 +449,7 @@ class BookList(object): f = open(self.file, "w") f.write("\n") f.write('\n') - for name in self.bookmap: + for name in sorted(self.bookmap): # enable a diff of archived copies book = self.get_book(name) dbname = book.get_dbname() f.write('\n' % (name, dbname) ) @@ -933,21 +935,26 @@ class BookReportSelector(ManagedWindow): """ store, the_iter = self.book_model.get_selected() if not the_iter: + WarningDialog(_('No selected book item'), + _('Please select a book item to configure.') + ) return data = self.book_model.get_data(the_iter, range(self.book_nr_cols)) row = self.book_model.get_selected_row() item = self.book.get_item(row) option_class = item.option_class - item_dialog = BookItemDialog(self.dbstate, self.uistate, option_class, - item.get_name(), - item.get_translated_name(), - self.track) + option_class.handler.set_default_stylesheet_name(item.get_style_name()) + item.is_from_saved_book = bool(self.book.get_name()) + item_dialog = BookItemDialog(self.dbstate, self.uistate, + item, self.track) while True: response = item_dialog.window.run() if response == gtk.RESPONSE_OK: # dialog will be closed by connect, now continue work while # rest of dialog is unresponsive, release when finished + style = option_class.handler.get_default_stylesheet_name() + item.set_style_name(style) subject = _get_subject(option_class, self.db) self.book_model.model.set_value(the_iter, 2, subject) self.book.set_item(row, item) @@ -1042,6 +1049,9 @@ class BookReportSelector(ManagedWindow): if self.book.item_list: BookReportDialog(self.dbstate, self.uistate, self.book, BookOptions) + else: + WarningDialog(_('No items'), _('This book has no items.')) + return self.close() def on_save_clicked(self, obj): @@ -1086,7 +1096,7 @@ class BookReportSelector(ManagedWindow): if book: self.open_book(book) self.name_entry.set_text(book.get_name()) - self.book.name = book.get_name() + self.book.set_name(book.get_name()) def on_edit_clicked(self, obj): """ @@ -1113,11 +1123,14 @@ class BookItemDialog(ReportDialog): in a way specific for this report. This is a book item dialog. """ - def __init__(self, dbstate, uistate, option_class, name, translated_name, - track=[]): + def __init__(self, dbstate, uistate, item, track=[]): + option_class = item.option_class + name = item.get_name() + translated_name = item.get_translated_name() self.category = CATEGORY_BOOK self.database = dbstate.db self.option_class = option_class + self.is_from_saved_book = item.is_from_saved_book ReportDialog.__init__(self, dbstate, uistate, option_class, name, translated_name, track) @@ -1138,6 +1151,43 @@ class BookItemDialog(ReportDialog): def parse_target_frame(self): """Target frame is not used.""" return 1 + + def init_options(self, option_class): + try: + if (issubclass(option_class, object) or # New-style class + isinstance(option_class, ClassType)): # Old-style class + self.options = option_class(self.raw_name, self.db) + except TypeError: + self.options = option_class + if not self.is_from_saved_book: + self.options.load_previous_values() + + def add_user_options(self): + """ + Generic method to add user options to the gui. + """ + if not hasattr(self.options, "menu"): + return + menu = self.options.menu + options_dict = self.options.options_dict + for category in menu.get_categories(): + for name in menu.get_option_names(category): + option = menu.get_option(category, name) + + # override option default with xml-saved value: + if name in options_dict: + option.set_value(options_dict[name]) + + widget, label = make_gui_option(option, self.dbstate, + self.uistate, self.track, + self.is_from_saved_book) + if widget is not None: + if label: + self.add_frame_option(category, + option.get_label(), + widget) + else: + self.add_frame_option(category, "", widget) #------------------------------------------------------------------------- # @@ -1193,26 +1243,30 @@ class BookReportDialog(DocReportDialog): def __init__(self, dbstate, uistate, book, options): self.format_menu = None self.options = options + self.is_from_saved_book = False self.page_html_added = False + self.book = book DocReportDialog.__init__(self, dbstate, uistate, options, 'book', _("Book Report")) - self.book = book self.options.options_dict['bookname'] = self.book.name self.database = dbstate.db self.selected_style = StyleSheet() for item in self.book.get_item_list(): + handler = item.option_class.handler + # Set up default style + handler.set_default_stylesheet_name(item.get_style_name()) default_style = StyleSheet() make_default_style = item.option_class.make_default_style make_default_style(default_style) # Read all style sheets available for this item - style_file = item.option_class.handler.get_stylesheet_savefile() + style_file = handler.get_stylesheet_savefile() style_list = StyleSheetList(style_file, default_style) # Get the selected stylesheet - style_name = item.option_class.handler.get_default_stylesheet_name() + style_name = handler.get_default_stylesheet_name() style_sheet = style_list.get_style_sheet(style_name) for this_style_name in style_sheet.get_paragraph_style_names(): @@ -1287,6 +1341,16 @@ class BookReportDialog(DocReportDialog): if self.open_with_app.get_active(): gui.utils.open_file_with_default_application(self.target_path) + def init_options(self, option_class): + try: + if (issubclass(option_class, object) or # New-style class + isinstance(option_class, ClassType)): # Old-style class + self.options = option_class(self.raw_name, self.db) + except TypeError: + self.options = option_class + if not self.is_from_saved_book: + self.options.load_previous_values() + #------------------------------------------------------------------------ # # Function to write books from command line @@ -1318,17 +1382,20 @@ def cl_report(database, name, category, options_str_dict): selected_style = StyleSheet() for item in book.get_item_list(): + handler = item.option_class.handler + # Set up default style + handler.set_default_stylesheet_name(item.get_style_name()) default_style = StyleSheet() make_default_style = item.option_class.make_default_style make_default_style(default_style) # Read all style sheets available for this item - style_file = item.option_class.handler.get_stylesheet_savefile() + style_file = handler.get_stylesheet_savefile() style_list = StyleSheetList(style_file, default_style) # Get the selected stylesheet - style_name = item.option_class.handler.get_default_stylesheet_name() + style_name = handler.get_default_stylesheet_name() style_sheet = style_list.get_style_sheet(style_name) for this_style_name in style_sheet.get_paragraph_style_names():