diff --git a/src/gui/plug/_guioptions.py b/src/gui/plug/_guioptions.py index cfd55b7e0..724795f1d 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 @@ -162,7 +162,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 @@ -224,7 +224,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() GObject.GObject.__init__( self, Gdk.color_parse(value) ) @@ -277,7 +277,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 @@ -349,7 +349,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 GObject.GObject.__init__(self) self.set_shadow_type(Gtk.ShadowType.IN) @@ -432,7 +432,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 GObject.GObject.__init__(self, self.__option.get_label()) self.set_active(self.__option.get_value()) @@ -488,7 +488,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): GObject.GObject.__init__(self) evtBox = Gtk.EventBox() self.__option = option @@ -581,7 +581,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 @@ -611,11 +611,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: @@ -705,7 +706,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 @@ -729,7 +730,7 @@ class GuiFamilyOption(Gtk.HBox): self.pack_start(pevt, False, True, 0) self.pack_end(family_button, False, True, 0) - self.__initialize_family() + self.__initialize_family(override) self.valuekey = self.__option.connect('value-changed', self.__value_changed) @@ -739,10 +740,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 = [] @@ -751,7 +752,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 @@ -891,7 +892,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 @@ -995,7 +996,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 @@ -1096,7 +1097,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 @@ -1273,7 +1274,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 @@ -1417,7 +1418,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 @@ -1608,7 +1609,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 @@ -1737,7 +1738,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 @@ -1777,7 +1778,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): GObject.GObject.__init__(self) self.__option = option self.__cbutton = [] @@ -1889,10 +1890,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 @@ -1909,7 +1914,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 0e0585b02..05659ee20 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 @@ -79,6 +79,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 @@ -446,7 +448,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) ) @@ -934,21 +936,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.ResponseType.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) @@ -1043,6 +1050,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): @@ -1087,7 +1097,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): """ @@ -1114,11 +1124,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) @@ -1139,6 +1152,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) #------------------------------------------------------------------------- # @@ -1194,26 +1244,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(): @@ -1288,6 +1342,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 @@ -1319,17 +1383,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():