478 lines
14 KiB
Python
478 lines
14 KiB
Python
|
#
|
||
|
# Gramps - a GTK+/GNOME based genealogy program
|
||
|
#
|
||
|
# Copyright (C) 2000-2006 Donald N. Allingham
|
||
|
#
|
||
|
# 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$
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# Standard python modules
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
import logging
|
||
|
_LOG = logging.getLogger(".widgets.monitoredwidgets")
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# GTK/Gnome modules
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
import gobject
|
||
|
import gtk
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# Gramps modules
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
import AutoComp
|
||
|
import DateEdit
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# MonitoredCheckbox class
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
class MonitoredCheckbox:
|
||
|
|
||
|
def __init__(self, obj, button, set_val, get_val, on_toggle=None, readonly = False):
|
||
|
self.button = button
|
||
|
self.button.connect('toggled', self._on_toggle)
|
||
|
self.on_toggle = on_toggle
|
||
|
self.obj = obj
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
self.button.set_active(get_val())
|
||
|
self.button.set_sensitive(not readonly)
|
||
|
|
||
|
def _on_toggle(self, obj):
|
||
|
self.set_val(obj.get_active())
|
||
|
if self.on_toggle:
|
||
|
self.on_toggle(self.get_val())
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# MonitoredEntry class
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
class MonitoredEntry:
|
||
|
|
||
|
def __init__(self, obj, set_val, get_val, read_only=False,
|
||
|
autolist=None, changed=None):
|
||
|
self.obj = obj
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
self.changed = changed
|
||
|
|
||
|
if get_val():
|
||
|
self.obj.set_text(get_val())
|
||
|
self.obj.connect('changed', self._on_change)
|
||
|
self.obj.set_editable(not read_only)
|
||
|
|
||
|
if autolist:
|
||
|
AutoComp.fill_entry(obj, autolist)
|
||
|
|
||
|
def reinit(self, set_val, get_val):
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
self.update()
|
||
|
|
||
|
def set_text(self, text):
|
||
|
self.obj.set_text(text)
|
||
|
|
||
|
def connect(self, signal, callback, *data):
|
||
|
self.obj.connect(signal, callback, *data)
|
||
|
|
||
|
def _on_change(self, obj):
|
||
|
self.set_val(unicode(obj.get_text()))
|
||
|
if self.changed:
|
||
|
self.changed(obj)
|
||
|
|
||
|
def force_value(self, value):
|
||
|
self.obj.set_text(value)
|
||
|
|
||
|
def get_value(self, value):
|
||
|
return unicode(self.obj.get_text())
|
||
|
|
||
|
def enable(self, value):
|
||
|
self.obj.set_sensitive(value)
|
||
|
self.obj.set_editable(value)
|
||
|
|
||
|
def grab_focus(self):
|
||
|
self.obj.grab_focus()
|
||
|
|
||
|
def update(self):
|
||
|
if self.get_val() is not None:
|
||
|
self.obj.set_text(self.get_val())
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# MonitoredSpinButton class
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
class MonitoredSpinButton:
|
||
|
"""
|
||
|
Class for signal handling of spinbuttons.
|
||
|
(Code is a modified copy of MonitoredEntry)
|
||
|
"""
|
||
|
|
||
|
def __init__(self, obj, set_val, get_val, read_only=False,
|
||
|
autolist=None, changed=None):
|
||
|
"""
|
||
|
@param obj: widget to be monitored
|
||
|
@type obj: gtk.SpinButton
|
||
|
@param set_val: callback to be called when obj is changed
|
||
|
@param get_val: callback to be called to retrieve value for obj
|
||
|
@param read_only: If SpinButton is read only.
|
||
|
"""
|
||
|
|
||
|
self.obj = obj
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
self.changed = changed
|
||
|
|
||
|
if get_val():
|
||
|
self.obj.set_value(get_val())
|
||
|
self.obj.connect('value-changed', self._on_change)
|
||
|
self.obj.set_editable(not read_only)
|
||
|
|
||
|
if autolist:
|
||
|
AutoComp.fill_entry(obj,autolist)
|
||
|
|
||
|
def reinit(self, set_val, get_val):
|
||
|
"""
|
||
|
Reinitialize class with the specified callback functions.
|
||
|
|
||
|
@param set_val: callback to be called when SpinButton is changed
|
||
|
@param get_val: callback to be called to retrieve value for SpinButton
|
||
|
"""
|
||
|
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
self.update()
|
||
|
|
||
|
def set_value(self, value):
|
||
|
"""
|
||
|
Set the value of the monitored widget to the specified value.
|
||
|
|
||
|
@param value: Value to be set.
|
||
|
"""
|
||
|
|
||
|
self.obj.set_value(value)
|
||
|
|
||
|
def connect(self, signal, callback):
|
||
|
"""
|
||
|
Connect the signal of monitored widget to the specified callback.
|
||
|
|
||
|
@param signal: Signal prototype for which a connection should be set up.
|
||
|
@param callback: Callback function to be called when signal is emitted.
|
||
|
"""
|
||
|
|
||
|
self.obj.connect(signal, callback)
|
||
|
|
||
|
def _on_change(self, obj):
|
||
|
"""
|
||
|
Event handler to be called when the monitored widget is changed.
|
||
|
|
||
|
@param obj: Widget that has been changed.
|
||
|
@type obj: gtk.SpinButton
|
||
|
"""
|
||
|
|
||
|
self.set_val(obj.get_value())
|
||
|
if self.changed:
|
||
|
self.changed(obj)
|
||
|
|
||
|
def force_value(self, value):
|
||
|
"""
|
||
|
Set the value of the monitored widget to the specified value.
|
||
|
|
||
|
@param value: Value to be set.
|
||
|
"""
|
||
|
|
||
|
self.obj.set_value(value)
|
||
|
|
||
|
def get_value(self):
|
||
|
"""
|
||
|
Get the current value of the monitored widget.
|
||
|
|
||
|
@returns: Current value of monitored widget.
|
||
|
"""
|
||
|
|
||
|
return self.obj.get_value()
|
||
|
|
||
|
def enable(self, value):
|
||
|
"""
|
||
|
Change the property editable and sensitive of the monitored widget to value.
|
||
|
|
||
|
@param value: If widget should be editable or deactivated.
|
||
|
@type value: bool
|
||
|
"""
|
||
|
|
||
|
self.obj.set_sensitive(value)
|
||
|
self.obj.set_editable(value)
|
||
|
|
||
|
def grab_focus(self):
|
||
|
"""
|
||
|
Assign the keyboard focus to the monitored widget.
|
||
|
"""
|
||
|
|
||
|
self.obj.grab_focus()
|
||
|
|
||
|
def update(self):
|
||
|
"""
|
||
|
Updates value of monitored SpinButton with the value returned by the get_val callback.
|
||
|
"""
|
||
|
|
||
|
if self.get_val():
|
||
|
self.obj.set_value(self.get_val())
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# MonitoredText class
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
class MonitoredText:
|
||
|
|
||
|
def __init__(self, obj, set_val, get_val, read_only=False):
|
||
|
self.buf = obj.get_buffer()
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
|
||
|
if get_val():
|
||
|
self.buf.set_text(get_val())
|
||
|
self.buf.connect('changed', self.on_change)
|
||
|
obj.set_editable(not read_only)
|
||
|
|
||
|
def on_change(self, obj):
|
||
|
s, e = self.buf.get_bounds()
|
||
|
self.set_val(unicode(self.buf.get_text(s, e, False)))
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# MonitoredType class
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
class MonitoredType:
|
||
|
|
||
|
def __init__(self, obj, set_val, get_val, mapping, custom, readonly=False,
|
||
|
custom_values=None):
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
|
||
|
self.obj = obj
|
||
|
|
||
|
val = get_val()
|
||
|
if val:
|
||
|
default = val[0]
|
||
|
else:
|
||
|
default = None
|
||
|
|
||
|
self.sel = AutoComp.StandardCustomSelector(
|
||
|
mapping, obj, custom, default, additional=custom_values)
|
||
|
|
||
|
self.set_val(self.sel.get_values())
|
||
|
self.obj.set_sensitive(not readonly)
|
||
|
self.obj.connect('changed', self.on_change)
|
||
|
|
||
|
def reinit(self, set_val, get_val):
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
self.update()
|
||
|
|
||
|
def update(self):
|
||
|
if self.get_val():
|
||
|
self.sel.set_values(self.get_val())
|
||
|
|
||
|
def on_change(self, obj):
|
||
|
self.set_val(self.sel.get_values())
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# MonitoredDataType class
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
class MonitoredDataType:
|
||
|
|
||
|
|
||
|
def __init__(self, obj, set_val, get_val, readonly=False,
|
||
|
custom_values=None, ignore_values=None):
|
||
|
"""
|
||
|
Constructor for the MonitoredDataType class.
|
||
|
|
||
|
@param obj: Existing ComboBoxEntry widget to use.
|
||
|
@type obj: gtk.ComboBoxEntry
|
||
|
@param set_val: The function that sets value of the type in the object
|
||
|
@type set_val: method
|
||
|
@param get_val: The function that gets value of the type in the object.
|
||
|
This returns a GrampsType, of which get_map returns all possible types
|
||
|
@type get_val: method
|
||
|
@param custom_values: Extra values to show in the combobox. These can be
|
||
|
text of custom type, tuple with type info or GrampsType class
|
||
|
@type : list of str, tuple or GrampsType
|
||
|
@ignore_values: list of values not to show in the combobox. If the result
|
||
|
of get_val is in these, it is not ignored
|
||
|
@type : list of int
|
||
|
"""
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
|
||
|
self.obj = obj
|
||
|
|
||
|
val = get_val()
|
||
|
|
||
|
if val:
|
||
|
default = int(val)
|
||
|
else:
|
||
|
default = None
|
||
|
|
||
|
map = get_val().get_map().copy()
|
||
|
if ignore_values :
|
||
|
for key in map.keys():
|
||
|
try :
|
||
|
i = ignore_values.index(key)
|
||
|
except ValueError:
|
||
|
i = None
|
||
|
if (not i==None) and (not ignore_values[i] == default) :
|
||
|
del map[key]
|
||
|
|
||
|
self.sel = AutoComp.StandardCustomSelector(
|
||
|
map,
|
||
|
obj,
|
||
|
get_val().get_custom(),
|
||
|
default,
|
||
|
additional=custom_values)
|
||
|
|
||
|
self.sel.set_values((int(get_val()), str(get_val())))
|
||
|
self.obj.set_sensitive(not readonly)
|
||
|
self.obj.connect('changed', self.on_change)
|
||
|
|
||
|
def reinit(self, set_val, get_val):
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
self.update()
|
||
|
|
||
|
def fix_value(self, value):
|
||
|
if value[0] == self.get_val().get_custom():
|
||
|
return value
|
||
|
else:
|
||
|
return (value[0], '')
|
||
|
|
||
|
def update(self):
|
||
|
val = self.get_val()
|
||
|
if type(val) == tuple :
|
||
|
self.sel.set_values(val)
|
||
|
else:
|
||
|
self.sel.set_values((int(val), str(val)))
|
||
|
|
||
|
def on_change(self, obj):
|
||
|
value = self.fix_value(self.sel.get_values())
|
||
|
self.set_val(value)
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# MonitoredMenu class
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
class MonitoredMenu:
|
||
|
|
||
|
def __init__(self, obj, set_val, get_val, mapping,
|
||
|
readonly=False, changed=None):
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
|
||
|
self.changed = changed
|
||
|
self.obj = obj
|
||
|
|
||
|
self.change_menu(mapping)
|
||
|
self.obj.connect('changed', self.on_change)
|
||
|
self.obj.set_sensitive(not readonly)
|
||
|
|
||
|
def force(self, value):
|
||
|
self.obj.set_active(value)
|
||
|
|
||
|
def change_menu(self, mapping):
|
||
|
self.data = {}
|
||
|
self.model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT)
|
||
|
index = 0
|
||
|
for t, v in mapping:
|
||
|
self.model.append(row=[t, v])
|
||
|
self.data[v] = index
|
||
|
index += 1
|
||
|
self.obj.set_model(self.model)
|
||
|
self.obj.set_active(self.data.get(self.get_val(), 0))
|
||
|
|
||
|
def on_change(self, obj):
|
||
|
self.set_val(self.model.get_value(obj.get_active_iter(), 1))
|
||
|
if self.changed:
|
||
|
self.changed()
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# MonitoredStrMenu class
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
class MonitoredStrMenu:
|
||
|
|
||
|
def __init__(self, obj, set_val, get_val, mapping, readonly=False):
|
||
|
self.set_val = set_val
|
||
|
self.get_val = get_val
|
||
|
|
||
|
self.obj = obj
|
||
|
self.model = gtk.ListStore(gobject.TYPE_STRING)
|
||
|
|
||
|
if len(mapping) > 20:
|
||
|
self.obj.set_wrap_width(3)
|
||
|
|
||
|
self.model.append(row=[''])
|
||
|
index = 0
|
||
|
self.data = ['']
|
||
|
|
||
|
default = get_val()
|
||
|
active = 0
|
||
|
|
||
|
for t, v in mapping:
|
||
|
self.model.append(row=[v])
|
||
|
self.data.append(t)
|
||
|
index += 1
|
||
|
if t == default:
|
||
|
active = index
|
||
|
|
||
|
self.obj.set_model(self.model)
|
||
|
self.obj.set_active(active)
|
||
|
self.obj.connect('changed', self.on_change)
|
||
|
self.obj.set_sensitive(not readonly)
|
||
|
|
||
|
def on_change(self, obj):
|
||
|
self.set_val(self.data[obj.get_active()])
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
#
|
||
|
# MonitoredDate class
|
||
|
#
|
||
|
#-------------------------------------------------------------------------
|
||
|
class MonitoredDate:
|
||
|
|
||
|
def __init__(self, field, button, value, uistate, track, readonly=False):
|
||
|
self.date = value
|
||
|
self.date_check = DateEdit.DateEdit(
|
||
|
self.date, field, button, uistate, track)
|
||
|
field.set_editable(not readonly)
|
||
|
button.set_sensitive(not readonly)
|
||
|
|