1952 lines
72 KiB
Python
1952 lines
72 KiB
Python
#
|
|
# Gramps - a GTK+/GNOME based genealogy program
|
|
#
|
|
# Copyright (C) 2007-2008 Brian G. Matherly
|
|
# Copyright (C) 2008,2010 Gary Burton
|
|
# Copyright (C) 2008 Craig J. Anderson
|
|
# Copyright (C) 2009 Nick Hall
|
|
# Copyright (C) 2010 Jakim Friant
|
|
# Copyright (C) 2011 Adam Stein <adam@csh.rit.edu>
|
|
# 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
|
|
# 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$
|
|
|
|
"""
|
|
Specific option handling for a GUI.
|
|
"""
|
|
from __future__ import unicode_literals
|
|
|
|
#------------------------------------------------------------------------
|
|
#
|
|
# python modules
|
|
#
|
|
#------------------------------------------------------------------------
|
|
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
|
_ = glocale.get_translation().gettext
|
|
import os
|
|
import sys
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# gtk modules
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
from gi.repository import Gtk
|
|
from gi.repository import Gdk
|
|
from gi.repository import GObject
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# gramps modules
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
from gramps.gen.utils.file import get_unicode_path_from_file_chooser
|
|
from ..utils import ProgressMeter
|
|
from ..pluginmanager import GuiPluginManager
|
|
from .. import widgets
|
|
from ..managedwindow import ManagedWindow
|
|
from ..dialog import OptionDialog
|
|
from ..selectors import SelectorFactory
|
|
from gramps.gen.display.name import displayer as _nd
|
|
from gramps.gen.filters import GenericFilterFactory, GenericFilter, rules
|
|
from gramps.gen.constfunc import cuni, STRTYPE
|
|
|
|
#------------------------------------------------------------------------
|
|
#
|
|
# Dialog window used to select a surname
|
|
#
|
|
#------------------------------------------------------------------------
|
|
class LastNameDialog(ManagedWindow):
|
|
"""
|
|
A dialog that allows the selection of a surname from the database.
|
|
"""
|
|
def __init__(self, database, uistate, track, surnames, skip_list=set()):
|
|
|
|
ManagedWindow.__init__(self, uistate, track, self)
|
|
flags = Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT
|
|
buttons = (Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT, Gtk.STOCK_OK,
|
|
Gtk.ResponseType.ACCEPT)
|
|
self.__dlg = Gtk.Dialog(None, uistate.window, flags, buttons)
|
|
self.__dlg.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
|
|
self.set_window(self.__dlg, None, _('Select surname'))
|
|
self.window.set_default_size(400, 400)
|
|
|
|
# build up a container to display all of the people of interest
|
|
self.__model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT)
|
|
self.__tree_view = Gtk.TreeView(self.__model)
|
|
col1 = Gtk.TreeViewColumn(_('Surname'), Gtk.CellRendererText(), text=0)
|
|
col2 = Gtk.TreeViewColumn(_('Count'), Gtk.CellRendererText(), text=1)
|
|
col1.set_resizable(True)
|
|
col2.set_resizable(True)
|
|
col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
|
col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
|
col1.set_sort_column_id(0)
|
|
col2.set_sort_column_id(1)
|
|
self.__tree_view.append_column(col1)
|
|
self.__tree_view.append_column(col2)
|
|
scrolled_window = Gtk.ScrolledWindow()
|
|
scrolled_window.add(self.__tree_view)
|
|
scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
|
scrolled_window.set_shadow_type(Gtk.ShadowType.OUT)
|
|
self.__dlg.vbox.pack_start(scrolled_window, True, True, 0)
|
|
scrolled_window.show_all()
|
|
|
|
if len(surnames) == 0:
|
|
# we could use database.get_surname_list(), but if we do that
|
|
# all we get is a list of names without a count...therefore
|
|
# we'll traverse the entire database ourself and build up a
|
|
# list that we can use
|
|
# for name in database.get_surname_list():
|
|
# self.__model.append([name, 0])
|
|
|
|
# build up the list of surnames, keeping track of the count for each
|
|
# name (this can be a lengthy process, so by passing in the
|
|
# dictionary we can be certain we only do this once)
|
|
progress = ProgressMeter(_('Finding Surnames'))
|
|
progress.set_pass(_('Finding surnames'),
|
|
database.get_number_of_people())
|
|
for person in database.iter_people():
|
|
progress.step()
|
|
key = person.get_primary_name().get_surname()
|
|
count = 0
|
|
if key in surnames:
|
|
count = surnames[key]
|
|
surnames[key] = count + 1
|
|
progress.close()
|
|
|
|
# insert the names and count into the model
|
|
for key in surnames:
|
|
if key.encode('iso-8859-1','xmlcharrefreplace') not in skip_list:
|
|
self.__model.append([key, surnames[key]])
|
|
|
|
# keep the list sorted starting with the most popular last name
|
|
self.__model.set_sort_column_id(1, Gtk.SortType.DESCENDING)
|
|
|
|
# the "OK" button should be enabled/disabled based on the selection of
|
|
# a row
|
|
self.__tree_selection = self.__tree_view.get_selection()
|
|
self.__tree_selection.set_mode(Gtk.SelectionMode.MULTIPLE)
|
|
self.__tree_selection.select_path(0)
|
|
|
|
def run(self):
|
|
"""
|
|
Display the dialog and return the selected surnames when done.
|
|
"""
|
|
response = self.__dlg.run()
|
|
surname_set = set()
|
|
if response == Gtk.ResponseType.ACCEPT:
|
|
(mode, paths) = self.__tree_selection.get_selected_rows()
|
|
for path in paths:
|
|
i = self.__model.get_iter(path)
|
|
surname = self.__model.get_value(i, 0)
|
|
surname_set.add(surname)
|
|
self.__dlg.destroy()
|
|
return surname_set
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiStringOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
class GuiStringOption(Gtk.Entry):
|
|
"""
|
|
This class displays an option that is a simple one-line string.
|
|
"""
|
|
def __init__(self, option, dbstate, uistate, track, override):
|
|
"""
|
|
@param option: The option to display.
|
|
@type option: gen.plug.menu.StringOption
|
|
@return: nothing
|
|
"""
|
|
GObject.GObject.__init__(self)
|
|
self.__option = option
|
|
self.set_text( self.__option.get_value() )
|
|
|
|
# Set up signal handlers when the widget value is changed
|
|
# from user interaction or programmatically. When handling
|
|
# a specific signal, we need to temporarily block the signal
|
|
# that would call the other signal handler.
|
|
self.changekey = self.connect('changed', self.__text_changed)
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.conkey = self.__option.connect('avail-changed', self.__update_avail)
|
|
self.__update_avail()
|
|
|
|
self.set_tooltip_text(self.__option.get_help())
|
|
|
|
def __text_changed(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the change of the value made by the user.
|
|
"""
|
|
self.__option.disable_signals()
|
|
self.__option.set_value( self.get_text() )
|
|
self.__option.enable_signals()
|
|
|
|
def __update_avail(self):
|
|
"""
|
|
Update the availability (sensitivity) of this widget.
|
|
"""
|
|
avail = self.__option.get_available()
|
|
self.set_sensitive(avail)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
self.handler_block(self.changekey)
|
|
self.set_text(self.__option.get_value())
|
|
self.handler_unblock(self.changekey)
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option.disconnect(self.conkey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiColorOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
class GuiColorOption(Gtk.ColorButton):
|
|
"""
|
|
This class displays an option that allows the selection of a colour.
|
|
"""
|
|
def __init__(self, option, dbstate, uistate, track, override):
|
|
self.__option = option
|
|
value = self.__option.get_value()
|
|
GObject.GObject.__init__(self)
|
|
self.set_color(Gdk.color_parse(self.__option.get_value()))
|
|
|
|
# Set up signal handlers when the widget value is changed
|
|
# from user interaction or programmatically. When handling
|
|
# a specific signal, we need to temporarily block the signal
|
|
# that would call the other signal handler.
|
|
self.changekey = self.connect('color-set', self.__color_changed)
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.set_tooltip_text(self.__option.get_help())
|
|
|
|
def __color_changed(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the change of color made by the user.
|
|
"""
|
|
colour = self.get_color()
|
|
value = '#%02x%02x%02x' % (
|
|
int(colour.red * 256 / 65536),
|
|
int(colour.green * 256 / 65536),
|
|
int(colour.blue * 256 / 65536))
|
|
|
|
self.__option.disable_signals()
|
|
self.__option.set_value(value)
|
|
self.__option.enable_signals()
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
self.handler_block(self.changekey)
|
|
self.set_color(Gdk.color_parse(self.__option.get_value()))
|
|
self.handler_unblock(self.changekey)
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiNumberOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
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, override):
|
|
self.__option = option
|
|
|
|
decimals = 0
|
|
step = self.__option.get_step()
|
|
adj = Gtk.Adjustment(1,
|
|
self.__option.get_min(),
|
|
self.__option.get_max(),
|
|
step)
|
|
|
|
# Calculate the number of decimal places if necessary
|
|
if step < 1:
|
|
import math
|
|
decimals = int(math.log10(step) * -1)
|
|
|
|
GObject.GObject.__init__(self, adjustment=adj, climb_rate=1, digits=decimals)
|
|
Gtk.SpinButton.set_numeric(self, True)
|
|
|
|
self.set_value(self.__option.get_value())
|
|
|
|
# Set up signal handlers when the widget value is changed
|
|
# from user interaction or programmatically. When handling
|
|
# a specific signal, we need to temporarily block the signal
|
|
# that would call the other signal handler.
|
|
self.changekey = self.connect('value_changed', self.__number_changed)
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.conkey = self.__option.connect('avail-changed', self.__update_avail)
|
|
self.__update_avail()
|
|
|
|
self.set_tooltip_text(self.__option.get_help())
|
|
|
|
def __number_changed(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the change of the value made by the user.
|
|
"""
|
|
vtype = type(self.__option.get_value())
|
|
|
|
self.__option.set_value( vtype(self.get_value()) )
|
|
|
|
def __update_avail(self):
|
|
"""
|
|
Update the availability (sensitivity) of this widget.
|
|
"""
|
|
avail = self.__option.get_available()
|
|
self.set_sensitive(avail)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
self.handler_block(self.changekey)
|
|
self.set_value(self.__option.get_value())
|
|
self.handler_unblock(self.changekey)
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option.disconnect(self.conkey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiTextOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
class GuiTextOption(Gtk.ScrolledWindow):
|
|
"""
|
|
This class displays an option that is a multi-line string.
|
|
"""
|
|
def __init__(self, option, dbstate, uistate, track, override):
|
|
self.__option = option
|
|
GObject.GObject.__init__(self)
|
|
self.set_shadow_type(Gtk.ShadowType.IN)
|
|
self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
|
|
|
# Add a TextView
|
|
value = self.__option.get_value()
|
|
gtext = Gtk.TextView()
|
|
gtext.set_size_request(-1, 70)
|
|
gtext.get_buffer().set_text("\n".join(value))
|
|
gtext.set_editable(1)
|
|
self.add(gtext)
|
|
self.__buff = gtext.get_buffer()
|
|
|
|
# Set up signal handlers when the widget value is changed
|
|
# from user interaction or programmatically. When handling
|
|
# a specific signal, we need to temporarily block the signal
|
|
# that would call the other signal handler.
|
|
self.bufcon = self.__buff.connect('changed', self.__text_changed)
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
# Required for tooltip
|
|
gtext.add_events(Gdk.EventMask.ENTER_NOTIFY_MASK)
|
|
gtext.add_events(Gdk.EventMask.LEAVE_NOTIFY_MASK)
|
|
gtext.set_tooltip_text(self.__option.get_help())
|
|
|
|
def __text_changed(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the change of the value made by the user.
|
|
"""
|
|
text_val = cuni( self.__buff.get_text( self.__buff.get_start_iter(),
|
|
self.__buff.get_end_iter(),
|
|
False) )
|
|
|
|
self.__option.disable_signals()
|
|
self.__option.set_value( text_val.split('\n') )
|
|
self.__option.enable_signals()
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
self.__buff.handler_block(self.bufcon)
|
|
|
|
value = self.__option.get_value()
|
|
|
|
# Can only set using a string. If we have a string value,
|
|
# we'll use that. If not, we'll assume a list and convert
|
|
# it into a single string by assuming each list element
|
|
# is separated by a newline.
|
|
if isinstance(value, STRTYPE):
|
|
self.__buff.set_text(value)
|
|
|
|
# Need to manually call the other handler so that the option
|
|
# value is changed to be a list. If left as a string,
|
|
# it would be treated as a list, meaning each character
|
|
# becomes a list element -- not what we want.
|
|
self.__text_changed(None)
|
|
else:
|
|
self.__buff.set_text("\n".join(value))
|
|
|
|
self.__buff.handler_unblock(self.bufcon)
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option = None
|
|
|
|
self.__buff.disconnect(self.bufcon)
|
|
self.__buff = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiBooleanOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
class GuiBooleanOption(Gtk.CheckButton):
|
|
"""
|
|
This class displays an option that is a boolean (True or False).
|
|
"""
|
|
def __init__(self, option, dbstate, uistate, track, override):
|
|
self.__option = option
|
|
GObject.GObject.__init__(self)
|
|
self.set_label(self.__option.get_label())
|
|
self.set_active(self.__option.get_value())
|
|
|
|
# Set up signal handlers when the widget value is changed
|
|
# from user interaction or programmatically. When handling
|
|
# a specific signal, we need to temporarily block the signal
|
|
# that would call the other signal handler.
|
|
self.changekey = self.connect('toggled', self.__state_changed)
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.conkey = self.__option.connect('avail-changed', self.__update_avail)
|
|
self.__update_avail()
|
|
|
|
self.set_tooltip_text(self.__option.get_help())
|
|
|
|
def __state_changed(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the change of the value made by the user.
|
|
"""
|
|
self.__option.set_value( self.get_active() )
|
|
|
|
def __update_avail(self):
|
|
"""
|
|
Update the availability (sensitivity) of this widget.
|
|
"""
|
|
avail = self.__option.get_available()
|
|
self.set_sensitive(avail)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
self.handler_block(self.changekey)
|
|
self.set_active(self.__option.get_value())
|
|
self.handler_unblock(self.changekey)
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option.disconnect(self.conkey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiEnumeratedListOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
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, override):
|
|
GObject.GObject.__init__(self)
|
|
evtBox = Gtk.EventBox()
|
|
self.__option = option
|
|
self.__combo = Gtk.ComboBoxText()
|
|
evtBox.add(self.__combo)
|
|
self.pack_start(evtBox, True, True, 0)
|
|
|
|
self.__update_options()
|
|
|
|
# Set up signal handlers when the widget value is changed
|
|
# from user interaction or programmatically. When handling
|
|
# a specific signal, we need to temporarily block the signal
|
|
# that would call the other signal handler.
|
|
self.changekey = self.__combo.connect('changed', self.__selection_changed)
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.conkey1 = self.__option.connect('options-changed', self.__update_options)
|
|
self.conkey2 = self.__option.connect('avail-changed', self.__update_avail)
|
|
self.__update_avail()
|
|
|
|
self.set_tooltip_text(self.__option.get_help())
|
|
|
|
def __selection_changed(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the change of the value made by the user.
|
|
"""
|
|
index = self.__combo.get_active()
|
|
if index < 0:
|
|
return
|
|
items = self.__option.get_items()
|
|
value, description = items[index] # IGNORE:W0612 - description is unused
|
|
|
|
# Don't disable the __option signals as is normally done for
|
|
# the other widgets or bad things happen (like other needed
|
|
# signals don't fire)
|
|
|
|
self.__option.set_value( value )
|
|
self.value_changed() # Allow overriding so that another class
|
|
# can add functionality
|
|
|
|
def value_changed(self):
|
|
pass
|
|
|
|
def __update_options(self):
|
|
"""
|
|
Handle the change of the available options.
|
|
"""
|
|
self.__combo.get_model().clear()
|
|
cur_val = self.__option.get_value()
|
|
active_index = 0
|
|
current_index = 0
|
|
for (value, description) in self.__option.get_items():
|
|
self.__combo.append_text(description)
|
|
if value == cur_val:
|
|
active_index = current_index
|
|
current_index += 1
|
|
self.__combo.set_active( active_index )
|
|
|
|
def __update_avail(self):
|
|
"""
|
|
Update the availability (sensitivity) of this widget.
|
|
"""
|
|
avail = self.__option.get_available()
|
|
self.set_sensitive(avail)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
self.__combo.handler_block(self.changekey)
|
|
self.__update_options()
|
|
self.__combo.handler_unblock(self.changekey)
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option.disconnect(self.conkey1)
|
|
self.__option.disconnect(self.conkey2)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiPersonOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
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, override):
|
|
"""
|
|
@param option: The option to display.
|
|
@type option: gen.plug.menu.PersonOption
|
|
@return: nothing
|
|
"""
|
|
GObject.GObject.__init__(self)
|
|
self.__option = option
|
|
self.__dbstate = dbstate
|
|
self.__db = dbstate.get_database()
|
|
self.__uistate = uistate
|
|
self.__track = track
|
|
self.__person_label = Gtk.Label()
|
|
self.__person_label.set_alignment(0.0, 0.5)
|
|
|
|
pevt = Gtk.EventBox()
|
|
pevt.add(self.__person_label)
|
|
person_button = widgets.SimpleButton(Gtk.STOCK_INDEX,
|
|
self.__get_person_clicked)
|
|
person_button.set_relief(Gtk.ReliefStyle.NORMAL)
|
|
|
|
self.pack_start(pevt, False, True, 0)
|
|
self.pack_end(person_button, False, True, 0)
|
|
|
|
gid = self.__option.get_value()
|
|
|
|
# Pick up the active person
|
|
person_handle = self.__uistate.get_active('Person')
|
|
person = self.__dbstate.db.get_person_from_handle(person_handle)
|
|
|
|
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:
|
|
person = self.__db.find_initial_person()
|
|
|
|
self.__update_person(person)
|
|
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.conkey = self.__option.connect('avail-changed', self.__update_avail)
|
|
self.__update_avail()
|
|
|
|
pevt.set_tooltip_text(self.__option.get_help())
|
|
person_button.set_tooltip_text(_('Select a different person'))
|
|
|
|
def __get_person_clicked(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the button to choose a different person.
|
|
"""
|
|
# Create a filter for the person selector.
|
|
rfilter = GenericFilter()
|
|
rfilter.set_logical_op('or')
|
|
rfilter.add_rule(rules.person.IsBookmarked([]))
|
|
rfilter.add_rule(rules.person.HasIdOf([self.__option.get_value()]))
|
|
|
|
# Add the database home person if one exists.
|
|
default_person = self.__db.get_default_person()
|
|
if default_person:
|
|
gid = default_person.get_gramps_id()
|
|
rfilter.add_rule(rules.person.HasIdOf([gid]))
|
|
|
|
# Add the selected person if one exists.
|
|
person_handle = self.__uistate.get_active('Person')
|
|
active_person = self.__dbstate.db.get_person_from_handle(person_handle)
|
|
if active_person:
|
|
gid = active_person.get_gramps_id()
|
|
rfilter.add_rule(rules.person.HasIdOf([gid]))
|
|
|
|
select_class = SelectorFactory('Person')
|
|
sel = select_class(self.__dbstate, self.__uistate, self.__track,
|
|
title=_('Select a person for the report'),
|
|
filter=rfilter )
|
|
person = sel.run()
|
|
self.__update_person(person)
|
|
|
|
def __update_person(self, person):
|
|
"""
|
|
Update the currently selected person.
|
|
"""
|
|
if person:
|
|
name = _nd.display(person)
|
|
gid = person.get_gramps_id()
|
|
self.__person_label.set_text( "%s (%s)" % (name, gid) )
|
|
self.__option.set_value(gid)
|
|
|
|
def __update_avail(self):
|
|
"""
|
|
Update the availability (sensitivity) of this widget.
|
|
"""
|
|
avail = self.__option.get_available()
|
|
self.set_sensitive(avail)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
gid = self.__option.get_value()
|
|
name = _nd.display(self.__db.get_person_from_gramps_id(gid))
|
|
|
|
self.__person_label.set_text("%s (%s)" % (name, gid))
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option.disconnect(self.conkey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiFamilyOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
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, override):
|
|
"""
|
|
@param option: The option to display.
|
|
@type option: gen.plug.menu.FamilyOption
|
|
@return: nothing
|
|
"""
|
|
GObject.GObject.__init__(self)
|
|
self.__option = option
|
|
self.__dbstate = dbstate
|
|
self.__db = dbstate.get_database()
|
|
self.__uistate = uistate
|
|
self.__track = track
|
|
self.__family_label = Gtk.Label()
|
|
self.__family_label.set_alignment(0.0, 0.5)
|
|
|
|
pevt = Gtk.EventBox()
|
|
pevt.add(self.__family_label)
|
|
family_button = widgets.SimpleButton(Gtk.STOCK_INDEX,
|
|
self.__get_family_clicked)
|
|
family_button.set_relief(Gtk.ReliefStyle.NORMAL)
|
|
|
|
self.pack_start(pevt, False, True, 0)
|
|
self.pack_end(family_button, False, True, 0)
|
|
|
|
self.__initialize_family(override)
|
|
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.conkey = self.__option.connect('avail-changed', self.__update_avail)
|
|
self.__update_avail()
|
|
|
|
pevt.set_tooltip_text(self.__option.get_help())
|
|
family_button.set_tooltip_text(_('Select a different family'))
|
|
|
|
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 is no active
|
|
family, try to find a family that the user is likely interested in.
|
|
"""
|
|
family_list = []
|
|
|
|
fid = self.__option.get_value()
|
|
|
|
# Use the active family if one is selected
|
|
family = self.__uistate.get_active('Family')
|
|
if family and not override:
|
|
family_list = [family]
|
|
else:
|
|
# Use the stored option value
|
|
family = self.__db.get_family_from_gramps_id(fid)
|
|
if family:
|
|
family_list = [family.get_handle()]
|
|
|
|
if not family_list:
|
|
# Next try the family of the active person
|
|
person_handle = self.__uistate.get_active('Person')
|
|
person = self.__dbstate.db.get_person_from_handle(person_handle)
|
|
if person:
|
|
family_list = person.get_family_handle_list()
|
|
|
|
if not family_list:
|
|
# Next try the family of the default person in the database.
|
|
person = self.__db.get_default_person()
|
|
if person:
|
|
family_list = person.get_family_handle_list()
|
|
|
|
if not family_list:
|
|
# Finally, take any family you can find.
|
|
for family in self.__db.iter_family_handles():
|
|
self.__update_family(family)
|
|
break
|
|
else:
|
|
self.__update_family(family_list[0])
|
|
|
|
def __get_family_clicked(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the button to choose a different family.
|
|
"""
|
|
# Create a filter for the person selector.
|
|
rfilter = GenericFilterFactory('Family')()
|
|
rfilter.set_logical_op('or')
|
|
|
|
# Add the current family
|
|
rfilter.add_rule(rules.family.HasIdOf([self.__option.get_value()]))
|
|
|
|
# Add all bookmarked families
|
|
rfilter.add_rule(rules.family.IsBookmarked([]))
|
|
|
|
# Add the families of the database home person if one exists.
|
|
default_person = self.__db.get_default_person()
|
|
if default_person:
|
|
family_list = default_person.get_family_handle_list()
|
|
for family_handle in family_list:
|
|
family = self.__db.get_family_from_handle(family_handle)
|
|
gid = family.get_gramps_id()
|
|
rfilter.add_rule(rules.family.HasIdOf([gid]))
|
|
|
|
# Add the families of the selected person if one exists.
|
|
# Same code as above one ! See bug #5032 feature request #5038
|
|
### active_person = self.__uistate.get_active('Person') ###
|
|
#active_person = self.__db.get_default_person()
|
|
#if active_person:
|
|
#family_list = active_person.get_family_handle_list()
|
|
#for family_handle in family_list:
|
|
#family = self.__db.get_family_from_handle(family_handle)
|
|
#gid = family.get_gramps_id()
|
|
#rfilter.add_rule(rules.family.HasIdOf([gid]))
|
|
|
|
select_class = SelectorFactory('Family')
|
|
sel = select_class(self.__dbstate, self.__uistate, self.__track,
|
|
filter=rfilter )
|
|
family = sel.run()
|
|
if family:
|
|
self.__update_family(family.get_handle())
|
|
|
|
def __update_family(self, handle):
|
|
"""
|
|
Update the currently selected family.
|
|
"""
|
|
if handle:
|
|
family = self.__dbstate.db.get_family_from_handle(handle)
|
|
family_id = family.get_gramps_id()
|
|
fhandle = family.get_father_handle()
|
|
mhandle = family.get_mother_handle()
|
|
|
|
if fhandle:
|
|
father = self.__db.get_person_from_handle(fhandle)
|
|
father_name = _nd.display(father)
|
|
else:
|
|
father_name = _("unknown father")
|
|
|
|
if mhandle:
|
|
mother = self.__db.get_person_from_handle(mhandle)
|
|
mother_name = _nd.display(mother)
|
|
else:
|
|
mother_name = _("unknown mother")
|
|
|
|
name = _("%(father_name)s and %(mother_name)s (%(family_id)s)") % {
|
|
'father_name': father_name,
|
|
'mother_name': mother_name,
|
|
'family_id': family_id}
|
|
|
|
self.__family_label.set_text( name )
|
|
self.__option.set_value(family_id)
|
|
|
|
def __update_avail(self):
|
|
"""
|
|
Update the availability (sensitivity) of this widget.
|
|
"""
|
|
avail = self.__option.get_available()
|
|
self.set_sensitive(avail)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
fid = self.__option.get_value()
|
|
handle = self.__db.get_family_from_gramps_id(fid).get_handle()
|
|
|
|
# Need to disable signals as __update_family() calls set_value()
|
|
# which would launch the 'value-changed' signal which is what
|
|
# we are reacting to here in the first place (don't need the
|
|
# signal repeated)
|
|
self.__option.disable_signals()
|
|
self.__update_family(handle)
|
|
self.__option.enable_signals()
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option.disconnect(self.conkey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# 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, override):
|
|
"""
|
|
@param option: The option to display.
|
|
@type option: gen.plug.menu.NoteOption
|
|
@return: nothing
|
|
"""
|
|
GObject.GObject.__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 = widgets.SimpleButton(Gtk.STOCK_INDEX,
|
|
self.__get_note_clicked)
|
|
note_button.set_relief(Gtk.ReliefStyle.NORMAL)
|
|
|
|
self.pack_start(pevt, False, True, 0)
|
|
self.pack_end(note_button, False, True, 0)
|
|
|
|
# Initialize to the current value
|
|
nid = self.__option.get_value()
|
|
note = self.__db.get_note_from_gramps_id(nid)
|
|
self.__update_note(note)
|
|
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.__option.connect('avail-changed', self.__update_avail)
|
|
self.__update_avail()
|
|
|
|
pevt.set_tooltip_text(self.__option.get_help())
|
|
note_button.set_tooltip_text(_('Select an existing note'))
|
|
|
|
def __get_note_clicked(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the button to choose a different note.
|
|
"""
|
|
select_class = SelectorFactory('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().split())
|
|
if len(txt) > 35:
|
|
txt = txt[:35] + "..."
|
|
txt = "%s [%s]" % (txt, note_id)
|
|
|
|
self.__note_label.set_text( txt )
|
|
self.__option.set_value(note_id)
|
|
else:
|
|
txt = "<i>%s</i>" % _('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)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
nid = self.__option.get_value()
|
|
note = self.__db.get_note_from_gramps_id(nid)
|
|
|
|
# Need to disable signals as __update_note() calls set_value()
|
|
# which would launch the 'value-changed' signal which is what
|
|
# we are reacting to here in the first place (don't need the
|
|
# signal repeated)
|
|
self.__option.disable_signals()
|
|
self.__update_note(note)
|
|
self.__option.enable_signals()
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# 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, override):
|
|
"""
|
|
@param option: The option to display.
|
|
@type option: gen.plug.menu.MediaOption
|
|
@return: nothing
|
|
"""
|
|
GObject.GObject.__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 = widgets.SimpleButton(Gtk.STOCK_INDEX,
|
|
self.__get_media_clicked)
|
|
media_button.set_relief(Gtk.ReliefStyle.NORMAL)
|
|
|
|
self.pack_start(pevt, False, True, 0)
|
|
self.pack_end(media_button, False, True, 0)
|
|
|
|
# Initialize to the current value
|
|
mid = self.__option.get_value()
|
|
media = self.__db.get_object_from_gramps_id(mid)
|
|
self.__update_media(media)
|
|
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.__option.connect('avail-changed', self.__update_avail)
|
|
self.__update_avail()
|
|
|
|
pevt.set_tooltip_text(self.__option.get_help())
|
|
media_button.set_tooltip_text(_('Select an existing media object'))
|
|
|
|
def __get_media_clicked(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the button to choose a different note.
|
|
"""
|
|
select_class = SelectorFactory('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 = "<i>%s</i>" % _('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)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
mid = self.__option.get_value()
|
|
media = self.__db.get_object_from_gramps_id(mid)
|
|
|
|
# Need to disable signals as __update_media() calls set_value()
|
|
# which would launch the 'value-changed' signal which is what
|
|
# we are reacting to here in the first place (don't need the
|
|
# signal repeated)
|
|
self.__option.disable_signals()
|
|
self.__update_media(media)
|
|
self.__option.enable_signals()
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiPersonListOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
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, override):
|
|
"""
|
|
@param option: The option to display.
|
|
@type option: gen.plug.menu.PersonListOption
|
|
@return: nothing
|
|
"""
|
|
GObject.GObject.__init__(self)
|
|
self.__option = option
|
|
self.__dbstate = dbstate
|
|
self.__db = dbstate.get_database()
|
|
self.__uistate = uistate
|
|
self.__track = track
|
|
self.set_size_request(150, 150)
|
|
|
|
self.__model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING)
|
|
self.__tree_view = Gtk.TreeView(self.__model)
|
|
col1 = Gtk.TreeViewColumn(_('Name' ), Gtk.CellRendererText(), text=0)
|
|
col2 = Gtk.TreeViewColumn(_('ID' ), Gtk.CellRendererText(), text=1)
|
|
col1.set_resizable(True)
|
|
col2.set_resizable(True)
|
|
col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
|
col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
|
col1.set_sort_column_id(0)
|
|
col2.set_sort_column_id(1)
|
|
self.__tree_view.append_column(col1)
|
|
self.__tree_view.append_column(col2)
|
|
self.__scrolled_window = Gtk.ScrolledWindow()
|
|
self.__scrolled_window.add(self.__tree_view)
|
|
self.__scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
|
|
Gtk.PolicyType.AUTOMATIC)
|
|
self.__scrolled_window.set_shadow_type(Gtk.ShadowType.OUT)
|
|
|
|
self.pack_start(self.__scrolled_window, True, True, 0)
|
|
|
|
self.__value_changed()
|
|
|
|
# now setup the '+' and '-' pushbutton for adding/removing people from
|
|
# the container
|
|
self.__add_person = widgets.SimpleButton(Gtk.STOCK_ADD,
|
|
self.__add_person_clicked)
|
|
self.__del_person = widgets.SimpleButton(Gtk.STOCK_REMOVE,
|
|
self.__del_person_clicked)
|
|
self.__vbbox = Gtk.VButtonBox()
|
|
self.__vbbox.add(self.__add_person)
|
|
self.__vbbox.add(self.__del_person)
|
|
self.__vbbox.set_layout(Gtk.ButtonBoxStyle.SPREAD)
|
|
self.pack_end(self.__vbbox, False, False, 0)
|
|
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.__tree_view.set_tooltip_text(self.__option.get_help())
|
|
|
|
def __add_person_clicked(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the add person button.
|
|
"""
|
|
# people we already have must be excluded
|
|
# so we don't list them multiple times
|
|
skip_list = set()
|
|
i = self.__model.get_iter_first()
|
|
while (i):
|
|
gid = self.__model.get_value(i, 1) # get the GID stored in column #1
|
|
person = self.__db.get_person_from_gramps_id(gid)
|
|
skip_list.add(person.get_handle())
|
|
i = self.__model.iter_next(i)
|
|
|
|
select_class = SelectorFactory('Person')
|
|
sel = select_class(self.__dbstate, self.__uistate,
|
|
self.__track, skip=skip_list)
|
|
person = sel.run()
|
|
if person:
|
|
name = _nd.display(person)
|
|
gid = person.get_gramps_id()
|
|
self.__model.append([name, gid])
|
|
|
|
# if this person has a spouse, ask if we should include the spouse
|
|
# in the list of "people of interest"
|
|
#
|
|
# NOTE: we may want to make this an optional thing, determined
|
|
# by the use of a parameter at the time this class is instatiated
|
|
family_list = person.get_family_handle_list()
|
|
for family_handle in family_list:
|
|
family = self.__db.get_family_from_handle(family_handle)
|
|
|
|
if person.get_handle() == family.get_father_handle():
|
|
spouse_handle = family.get_mother_handle()
|
|
else:
|
|
spouse_handle = family.get_father_handle()
|
|
|
|
if spouse_handle and (spouse_handle not in skip_list):
|
|
spouse = self.__db.get_person_from_handle(
|
|
spouse_handle)
|
|
spouse_name = _nd.display(spouse)
|
|
text = _('Also include %s?') % spouse_name
|
|
|
|
prompt = OptionDialog(_('Select Person'),
|
|
text,
|
|
_('No'), None,
|
|
_('Yes'), None)
|
|
if prompt.get_response() == Gtk.ResponseType.YES:
|
|
gid = spouse.get_gramps_id()
|
|
self.__model.append([spouse_name, gid])
|
|
|
|
self.__update_value()
|
|
|
|
def __del_person_clicked(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the delete person button.
|
|
"""
|
|
(path, column) = self.__tree_view.get_cursor()
|
|
if (path):
|
|
i = self.__model.get_iter(path)
|
|
self.__model.remove(i)
|
|
self.__update_value()
|
|
|
|
def __update_value(self):
|
|
"""
|
|
Parse the object and return.
|
|
"""
|
|
gidlist = ''
|
|
i = self.__model.get_iter_first()
|
|
while (i):
|
|
gid = self.__model.get_value(i, 1)
|
|
gidlist = gidlist + gid + ' '
|
|
i = self.__model.iter_next(i)
|
|
|
|
# Supress signals so that the set_value() handler
|
|
# (__value_changed()) doesn't get called
|
|
self.__option.disable_signals()
|
|
self.__option.set_value(gidlist)
|
|
self.__option.enable_signals()
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
value = self.__option.get_value()
|
|
|
|
if not isinstance(value, STRTYPE):
|
|
# Convert array into a string
|
|
# (convienence so that programmers can
|
|
# set value using a list)
|
|
value = " ".join(value)
|
|
|
|
# Need to change __option value to be the string
|
|
|
|
self.__option.disable_signals()
|
|
self.__option.set_value(value)
|
|
self.__option.enable_signals()
|
|
|
|
# Remove all entries (the new values will REPLACE
|
|
# rather than APPEND)
|
|
self.__model.clear()
|
|
|
|
for gid in value.split():
|
|
person = self.__db.get_person_from_gramps_id(gid)
|
|
if person:
|
|
name = _nd.display(person)
|
|
self.__model.append([name, gid])
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiPlaceListOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
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, override):
|
|
"""
|
|
@param option: The option to display.
|
|
@type option: gen.plug.menu.PlaceListOption
|
|
@return: nothing
|
|
"""
|
|
GObject.GObject.__init__(self)
|
|
self.__option = option
|
|
self.__dbstate = dbstate
|
|
self.__db = dbstate.get_database()
|
|
self.__uistate = uistate
|
|
self.__track = track
|
|
self.set_size_request(150, 150)
|
|
|
|
self.__model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING)
|
|
self.__tree_view = Gtk.TreeView(self.__model)
|
|
col1 = Gtk.TreeViewColumn(_('Place' ), Gtk.CellRendererText(), text=0)
|
|
col2 = Gtk.TreeViewColumn(_('ID' ), Gtk.CellRendererText(), text=1)
|
|
col1.set_resizable(True)
|
|
col2.set_resizable(True)
|
|
col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
|
col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
|
col1.set_sort_column_id(0)
|
|
col2.set_sort_column_id(1)
|
|
self.__tree_view.append_column(col1)
|
|
self.__tree_view.append_column(col2)
|
|
self.__scrolled_window = Gtk.ScrolledWindow()
|
|
self.__scrolled_window.add(self.__tree_view)
|
|
self.__scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
|
|
Gtk.PolicyType.AUTOMATIC)
|
|
self.__scrolled_window.set_shadow_type(Gtk.ShadowType.OUT)
|
|
|
|
self.pack_start(self.__scrolled_window, True, True, 0)
|
|
|
|
self.__value_changed()
|
|
|
|
# now setup the '+' and '-' pushbutton for adding/removing places from
|
|
# the container
|
|
self.__add_place = widgets.SimpleButton(Gtk.STOCK_ADD,
|
|
self.__add_place_clicked)
|
|
self.__del_place = widgets.SimpleButton(Gtk.STOCK_REMOVE,
|
|
self.__del_place_clicked)
|
|
self.__vbbox = Gtk.VButtonBox()
|
|
self.__vbbox.add(self.__add_place)
|
|
self.__vbbox.add(self.__del_place)
|
|
self.__vbbox.set_layout(Gtk.ButtonBoxStyle.SPREAD)
|
|
self.pack_end(self.__vbbox, False, False, 0)
|
|
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.__tree_view.set_tooltip_text(self.__option.get_help())
|
|
|
|
def __add_place_clicked(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the add place button.
|
|
"""
|
|
# places we already have must be excluded
|
|
# so we don't list them multiple times
|
|
skip_list = set()
|
|
i = self.__model.get_iter_first()
|
|
while (i):
|
|
gid = self.__model.get_value(i, 1) # get the GID stored in column #1
|
|
place = self.__db.get_place_from_gramps_id(gid)
|
|
skip_list.add(place.get_handle())
|
|
i = self.__model.iter_next(i)
|
|
|
|
select_class = SelectorFactory('Place')
|
|
sel = select_class(self.__dbstate, self.__uistate,
|
|
self.__track, skip=skip_list)
|
|
place = sel.run()
|
|
if place:
|
|
place_name = place.get_title()
|
|
gid = place.get_gramps_id()
|
|
self.__model.append([place_name, gid])
|
|
self.__update_value()
|
|
|
|
def __del_place_clicked(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the delete place button.
|
|
"""
|
|
(path, column) = self.__tree_view.get_cursor()
|
|
if (path):
|
|
i = self.__model.get_iter(path)
|
|
self.__model.remove(i)
|
|
self.__update_value()
|
|
|
|
def __update_value(self):
|
|
"""
|
|
Parse the object and return.
|
|
"""
|
|
gidlist = ''
|
|
i = self.__model.get_iter_first()
|
|
while (i):
|
|
gid = self.__model.get_value(i, 1)
|
|
gidlist = gidlist + gid + ' '
|
|
i = self.__model.iter_next(i)
|
|
self.__option.set_value(gidlist)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
value = self.__option.get_value()
|
|
|
|
if not isinstance(value, STRTYPE):
|
|
# Convert array into a string
|
|
# (convienence so that programmers can
|
|
# set value using a list)
|
|
value = " ".join(value)
|
|
|
|
# Need to change __option value to be the string
|
|
|
|
self.__option.disable_signals()
|
|
self.__option.set_value(value)
|
|
self.__option.enable_signals()
|
|
|
|
# Remove all entries (the new values will REPLACE
|
|
# rather than APPEND)
|
|
self.__model.clear()
|
|
|
|
for gid in value.split():
|
|
place = self.__db.get_place_from_gramps_id(gid)
|
|
if place:
|
|
place_name = place.get_title()
|
|
self.__model.append([place_name, gid])
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiSurnameColorOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
class GuiSurnameColorOption(Gtk.HBox):
|
|
"""
|
|
This class displays a widget that allows multiple surnames to be
|
|
selected from the database, and to assign a colour (not necessarily
|
|
unique) to each one.
|
|
"""
|
|
def __init__(self, option, dbstate, uistate, track, override):
|
|
"""
|
|
@param option: The option to display.
|
|
@type option: gen.plug.menu.SurnameColorOption
|
|
@return: nothing
|
|
"""
|
|
GObject.GObject.__init__(self)
|
|
self.__option = option
|
|
self.__dbstate = dbstate
|
|
self.__db = dbstate.get_database()
|
|
self.__uistate = uistate
|
|
self.__track = track
|
|
self.set_size_request(150, 150)
|
|
|
|
# This will get populated the first time the dialog is run,
|
|
# and used each time after.
|
|
self.__surnames = {} # list of surnames and count
|
|
|
|
self.__model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING)
|
|
self.__tree_view = Gtk.TreeView(self.__model)
|
|
self.__tree_view.connect('row-activated', self.__row_clicked)
|
|
col1 = Gtk.TreeViewColumn(_('Surname'), Gtk.CellRendererText(), text=0)
|
|
col2 = Gtk.TreeViewColumn(_('Color'), Gtk.CellRendererText(), text=1)
|
|
col1.set_resizable(True)
|
|
col2.set_resizable(True)
|
|
col1.set_sort_column_id(0)
|
|
col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
|
col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
|
self.__tree_view.append_column(col1)
|
|
self.__tree_view.append_column(col2)
|
|
self.scrolled_window = Gtk.ScrolledWindow()
|
|
self.scrolled_window.add(self.__tree_view)
|
|
self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
|
|
Gtk.PolicyType.AUTOMATIC)
|
|
self.scrolled_window.set_shadow_type(Gtk.ShadowType.OUT)
|
|
self.pack_start(self.scrolled_window, True, True, 0)
|
|
|
|
self.add_surname = widgets.SimpleButton(Gtk.STOCK_ADD,
|
|
self.__add_clicked)
|
|
self.del_surname = widgets.SimpleButton(Gtk.STOCK_REMOVE,
|
|
self.__del_clicked)
|
|
self.vbbox = Gtk.VButtonBox()
|
|
self.vbbox.add(self.add_surname)
|
|
self.vbbox.add(self.del_surname)
|
|
self.vbbox.set_layout(Gtk.ButtonBoxStyle.SPREAD)
|
|
self.pack_end(self.vbbox, False, False, 0)
|
|
|
|
self.__value_changed()
|
|
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.__tree_view.set_tooltip_text(self.__option.get_help())
|
|
|
|
def __add_clicked(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the the add surname button.
|
|
"""
|
|
skip_list = set()
|
|
i = self.__model.get_iter_first()
|
|
while (i):
|
|
surname = self.__model.get_value(i, 0)
|
|
skip_list.add(surname.encode('iso-8859-1','xmlcharrefreplace'))
|
|
i = self.__model.iter_next(i)
|
|
|
|
ln_dialog = LastNameDialog(self.__db, self.__uistate,
|
|
self.__track, self.__surnames, skip_list)
|
|
surname_set = ln_dialog.run()
|
|
for surname in surname_set:
|
|
self.__model.append([surname, '#ffffff'])
|
|
self.__update_value()
|
|
|
|
def __del_clicked(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the the delete surname button.
|
|
"""
|
|
(path, column) = self.__tree_view.get_cursor()
|
|
if (path):
|
|
i = self.__model.get_iter(path)
|
|
self.__model.remove(i)
|
|
self.__update_value()
|
|
|
|
def __row_clicked(self, treeview, path, column):
|
|
"""
|
|
Handle the case of a row being clicked on.
|
|
"""
|
|
# get the surname and colour value for this family
|
|
i = self.__model.get_iter(path)
|
|
surname = self.__model.get_value(i, 0)
|
|
colour = Gdk.color_parse(self.__model.get_value(i, 1))
|
|
|
|
title = _('Select color for %s') % surname
|
|
colour_dialog = Gtk.ColorSelectionDialog(title)
|
|
colorsel = colour_dialog.colorsel
|
|
colorsel.set_current_color(colour)
|
|
response = colour_dialog.run()
|
|
|
|
if response == Gtk.ResponseType.OK:
|
|
colour = colorsel.get_current_color()
|
|
colour_name = '#%02x%02x%02x' % (
|
|
int(colour.red *256/65536),
|
|
int(colour.green*256/65536),
|
|
int(colour.blue *256/65536))
|
|
self.__model.set_value(i, 1, colour_name)
|
|
|
|
colour_dialog.destroy()
|
|
self.__update_value()
|
|
|
|
def __update_value(self):
|
|
"""
|
|
Parse the object and return.
|
|
"""
|
|
surname_colours = ''
|
|
i = self.__model.get_iter_first()
|
|
while (i):
|
|
surname = self.__model.get_value(i, 0)
|
|
#surname = surname.encode('iso-8859-1','xmlcharrefreplace')
|
|
colour = self.__model.get_value(i, 1)
|
|
# Tried to use a dictionary, and tried to save it as a tuple,
|
|
# but coulnd't get this to work right -- this is lame, but now
|
|
# the surnames and colours are saved as a plain text string
|
|
#
|
|
# Hmmm...putting whitespace between the fields causes
|
|
# problems when the surname has whitespace -- for example,
|
|
# with surnames like "Del Monte". So now we insert a non-
|
|
# whitespace character which is unlikely to appear in
|
|
# a surname. (See bug report #2162.)
|
|
surname_colours += surname + '\xb0' + colour + '\xb0'
|
|
i = self.__model.iter_next(i)
|
|
self.__option.set_value( surname_colours )
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
value = self.__option.get_value()
|
|
|
|
if not isinstance(value, STRTYPE):
|
|
# Convert dictionary into a string
|
|
# (convienence so that programmers can
|
|
# set value using a dictionary)
|
|
value_str = ""
|
|
|
|
for name in value:
|
|
value_str += "%s\xb0%s\xb0" % (name, value[name])
|
|
|
|
value = value_str
|
|
|
|
# Need to change __option value to be the string
|
|
|
|
self.__option.disable_signals()
|
|
self.__option.set_value(value)
|
|
self.__option.enable_signals()
|
|
|
|
# Remove all entries (the new values will REPLACE
|
|
# rather than APPEND)
|
|
self.__model.clear()
|
|
|
|
# populate the surname/colour treeview
|
|
#
|
|
# For versions prior to 3.0.2, the fields were delimited with
|
|
# whitespace. However, this causes problems when the surname
|
|
# also has a space within it. When populating the control,
|
|
# support both the new and old format -- look for the \xb0
|
|
# delimiter, and if it isn't there, assume this is the old-
|
|
# style space-delimited format. (Bug #2162.)
|
|
if (value.find('\xb0') >= 0):
|
|
tmp = value.split('\xb0')
|
|
else:
|
|
tmp = value.split(' ')
|
|
while len(tmp) > 1:
|
|
surname = tmp.pop(0)
|
|
colour = tmp.pop(0)
|
|
self.__model.append([surname, colour])
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiDestinationOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
class GuiDestinationOption(Gtk.HBox):
|
|
"""
|
|
This class displays an option that allows the user to select a
|
|
DestinationOption.
|
|
"""
|
|
def __init__(self, option, dbstate, uistate, track, override):
|
|
"""
|
|
@param option: The option to display.
|
|
@type option: gen.plug.menu.DestinationOption
|
|
@return: nothing
|
|
"""
|
|
GObject.GObject.__init__(self)
|
|
self.__option = option
|
|
self.__entry = Gtk.Entry()
|
|
self.__entry.set_text( self.__option.get_value() )
|
|
|
|
self.__button = Gtk.Button()
|
|
img = Gtk.Image()
|
|
img.set_from_stock(Gtk.STOCK_OPEN, Gtk.IconSize.BUTTON)
|
|
self.__button.add(img)
|
|
self.__button.connect('clicked', self.__select_file)
|
|
|
|
self.pack_start(self.__entry, True, True, 0)
|
|
self.pack_end(self.__button, False, False, 0)
|
|
|
|
# Set up signal handlers when the widget value is changed
|
|
# from user interaction or programmatically. When handling
|
|
# a specific signal, we need to temporarily block the signal
|
|
# that would call the other signal handler.
|
|
self.changekey = self.__entry.connect('changed', self.__text_changed)
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.conkey1 = self.__option.connect('options-changed', self.__option_changed)
|
|
self.conkey2 = self.__option.connect('avail-changed', self.__update_avail)
|
|
self.__update_avail()
|
|
|
|
self.set_tooltip_text(self.__option.get_help())
|
|
|
|
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() )
|
|
|
|
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.FileChooserAction.SELECT_FOLDER
|
|
else:
|
|
my_action = Gtk.FileChooserAction.SAVE
|
|
|
|
fcd = Gtk.FileChooserDialog(_("Save As"), action=my_action,
|
|
buttons=(Gtk.STOCK_CANCEL,
|
|
Gtk.ResponseType.CANCEL,
|
|
Gtk.STOCK_OPEN,
|
|
Gtk.ResponseType.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.ResponseType.OK:
|
|
path = get_unicode_path_from_file_chooser(fcd.get_filename())
|
|
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 __text_changed(self, obj): # IGNORE:W0613 - obj is unused
|
|
"""
|
|
Handle the change of the value made by the user.
|
|
"""
|
|
self.__option.disable_signals()
|
|
self.__option.set_value( self.__entry.get_text() )
|
|
self.__option.enable_signals()
|
|
|
|
def __update_avail(self):
|
|
"""
|
|
Update the availability (sensitivity) of this widget.
|
|
"""
|
|
avail = self.__option.get_available()
|
|
self.set_sensitive(avail)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
self.__entry.handler_block(self.changekey)
|
|
self.__entry.set_text(self.__option.get_value())
|
|
self.__entry.handler_unblock(self.changekey)
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option.disconnect(self.conkey1)
|
|
self.__option.disconnect(self.conkey2)
|
|
self.__option = None
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiStyleOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
class GuiStyleOption(GuiEnumeratedListOption):
|
|
"""
|
|
This class displays a StyleOption.
|
|
"""
|
|
def __init__(self, option, dbstate, uistate, track, override):
|
|
"""
|
|
@param option: The option to display.
|
|
@type option: gen.plug.menu.StyleOption
|
|
@return: nothing
|
|
"""
|
|
GuiEnumeratedListOption.__init__(self, option, dbstate,
|
|
uistate, track)
|
|
self.__option = option
|
|
|
|
self.__button = Gtk.Button("%s..." % _("Style Editor"))
|
|
self.__button.connect('clicked', self.__on_style_edit_clicked)
|
|
|
|
self.pack_end(self.__button, False, False)
|
|
|
|
def __on_style_edit_clicked(self, *obj):
|
|
"""The user has clicked on the 'Edit Styles' button. Create a
|
|
style sheet editor object and let them play. When they are
|
|
done, update the displayed styles."""
|
|
from gramps.gen.plug.docgen import StyleSheetList
|
|
from .report._styleeditor import StyleListDisplay
|
|
style_list = StyleSheetList(self.__option.get_style_file(),
|
|
self.__option.get_default_style())
|
|
StyleListDisplay(style_list, None, None)
|
|
|
|
new_items = []
|
|
for style_name in style_list.get_style_names():
|
|
new_items.append( (style_name, style_name) )
|
|
self.__option.set_items(new_items)
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GuiBooleanListOption class
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
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, override):
|
|
GObject.GObject.__init__(self)
|
|
self.__option = option
|
|
self.__cbutton = []
|
|
|
|
COLUMNS = 2 # Number of checkbox columns
|
|
column = []
|
|
for i in range(COLUMNS):
|
|
vbox = Gtk.VBox()
|
|
self.pack_start(vbox, True, True, 0)
|
|
column.append(vbox)
|
|
vbox.show()
|
|
|
|
counter = 0
|
|
default = option.get_value().split(',')
|
|
for description in option.get_descriptions():
|
|
button = Gtk.CheckButton(description)
|
|
self.__cbutton.append(button)
|
|
if counter < len(default):
|
|
if default[counter] == 'True':
|
|
button.set_active(True)
|
|
button.connect("toggled", self.__list_changed)
|
|
column[counter % COLUMNS].pack_start(button, True, True, 0)
|
|
button.show()
|
|
counter += 1
|
|
|
|
self.valuekey = self.__option.connect('value-changed', self.__value_changed)
|
|
|
|
self.__option.connect('avail-changed', self.__update_avail)
|
|
self.__update_avail()
|
|
|
|
self.set_tooltip_text(self.__option.get_help())
|
|
|
|
def __list_changed(self, button):
|
|
"""
|
|
Handle the change of the value made by the user.
|
|
"""
|
|
value = ''
|
|
for button in self.__cbutton:
|
|
value = value + str(button.get_active()) + ','
|
|
value = value[:len(value)-1]
|
|
|
|
self.__option.disable_signals()
|
|
self.__option.set_value(value)
|
|
self.__option.enable_signals()
|
|
|
|
def __update_avail(self):
|
|
"""
|
|
Update the availability (sensitivity) of this widget.
|
|
"""
|
|
avail = self.__option.get_available()
|
|
self.set_sensitive(avail)
|
|
|
|
def __value_changed(self):
|
|
"""
|
|
Handle the change made programmatically
|
|
"""
|
|
value = self.__option.get_value()
|
|
|
|
self.__option.disable_signals()
|
|
|
|
for button in self.__cbutton:
|
|
for key in value:
|
|
if key == button.get_label():
|
|
bool_value = (value[key] == "True" or value[key] == True)
|
|
button.set_active(bool_value)
|
|
|
|
# Update __option value so that it's correct
|
|
self.__list_changed(None)
|
|
|
|
self.__option.enable_signals()
|
|
|
|
def clean_up(self):
|
|
"""
|
|
remove stuff that blocks garbage collection
|
|
"""
|
|
self.__option.disconnect(self.valuekey)
|
|
self.__option = None
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
# #
|
|
# Table mapping menu types to gui widgets used in make_gui_option function #
|
|
# #
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
from gramps.gen.plug import menu as menu
|
|
_OPTIONS = (
|
|
|
|
(menu.BooleanListOption, True, GuiBooleanListOption),
|
|
(menu.BooleanOption, False, GuiBooleanOption),
|
|
(menu.ColorOption, True, GuiColorOption),
|
|
(menu.DestinationOption, True, GuiDestinationOption),
|
|
(menu.EnumeratedListOption, True, GuiEnumeratedListOption),
|
|
(menu.FamilyOption, True, GuiFamilyOption),
|
|
(menu.MediaOption, True, GuiMediaOption),
|
|
(menu.NoteOption, True, GuiNoteOption),
|
|
(menu.NumberOption, True, GuiNumberOption),
|
|
(menu.PersonListOption, True, GuiPersonListOption),
|
|
(menu.PersonOption, True, GuiPersonOption),
|
|
(menu.PlaceListOption, True, GuiPlaceListOption),
|
|
(menu.StringOption, True, GuiStringOption),
|
|
(menu.StyleOption, True, GuiStyleOption),
|
|
(menu.SurnameColorOption, True, GuiSurnameColorOption),
|
|
(menu.TextOption, True, GuiTextOption),
|
|
|
|
# This entry must be last!
|
|
|
|
(menu.Option, None, None),
|
|
|
|
)
|
|
del menu
|
|
|
|
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
|
|
pmgr = GuiPluginManager.get_instance()
|
|
external_options = pmgr.get_external_opt_dict()
|
|
if option.__class__ in external_options:
|
|
widget = external_options[option.__class__]
|
|
else:
|
|
for type_, label, widget in _OPTIONS:
|
|
if isinstance(option, type_):
|
|
break
|
|
else:
|
|
raise AttributeError(
|
|
"can't make GuiOption: unknown option type: '%s'" % option)
|
|
|
|
if widget:
|
|
widget = widget(option, dbstate, uistate, track, override)
|
|
|
|
return widget, label
|
|
|
|
def add_gui_options(dialog):
|
|
"""
|
|
Stand-alone function to add user options to the GUI.
|
|
"""
|
|
if not hasattr(dialog.options, "menu"):
|
|
return
|
|
menu = dialog.options.menu
|
|
options_dict = dialog.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, dialog.dbstate,
|
|
dialog.uistate, dialog.track)
|
|
if widget is not None:
|
|
if label:
|
|
dialog.add_frame_option(category,
|
|
option.get_label(),
|
|
widget)
|
|
else:
|
|
dialog.add_frame_option(category, "", widget)
|