Reorganize custom widgets into a new 'widgets' package.

4. Blow up 'grampswidgets' module into several smaller modules.
Also move 'objectentry' module out from 'widgets' to src/, otherwise there
would be circular dependency between the 'Editors' and 'widgets' packages.


svn: r10703
This commit is contained in:
Zsolt Foldvari 2008-05-11 16:22:14 +00:00
parent 75a04613be
commit c6203b282b
17 changed files with 1778 additions and 1284 deletions

View File

@ -44,11 +44,12 @@ import Config
import gen.lib
import GrampsDisplay
from Editors import EditPrimary
from objectentries import PlaceEntry
from QuestionDialog import ErrorDialog
from DisplayTabs import (SourceEmbedList, NoteTab, GalleryTab,
EventBackRefList, AttrEmbedList)
from widgets import (MonitoredEntry, PlaceEntry, PrivacyButton,
from widgets import (MonitoredEntry, PrivacyButton,
MonitoredDataType, MonitoredDate)
#-------------------------------------------------------------------------

View File

@ -45,10 +45,12 @@ import gen.lib
from DisplayTabs import (SourceEmbedList, NoteTab, GalleryTab,
EventBackRefList, AttrEmbedList)
from widgets import (PrivacyButton, MonitoredEntry, PlaceEntry,
from widgets import (PrivacyButton, MonitoredEntry,
MonitoredDate, MonitoredDataType)
from _EditReference import RefTab, EditReference
from objectentries import PlaceEntry
#-------------------------------------------------------------------------
#
# Constants

View File

@ -52,9 +52,10 @@ from BasicUtils import name_displayer
import LdsUtils
from _EditSecondary import EditSecondary
from objectentries import PlaceEntry
from DisplayTabs import SourceEmbedList,NoteTab
from widgets import (PrivacyButton, MonitoredDate, PlaceEntry,
from widgets import (PrivacyButton, MonitoredDate,
MonitoredMenu, MonitoredStrMenu)
_DATA_MAP = {

View File

@ -38,4 +38,3 @@ from _EditSourceRef import *
from _EditUrl import *
from _EditPersonRef import *
from _EditChildRef import *

View File

@ -81,7 +81,8 @@ gdir_PYTHON = \
ViewManager.py\
UndoHistory.py\
PlaceUtils.py\
ProgressDialog.py
ProgressDialog.py \
objectentries.py
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo

400
src/objectentries.py Normal file
View File

@ -0,0 +1,400 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2007-2008 The Gramps Developers
#
# 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 cPickle as pickle
import logging
_LOG = logging.getLogger(".objectentries")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from gen.lib import (Place, MediaObject, Note)
from Editors._EditPlace import EditPlace
from Editors._EditMedia import EditMedia
from Editors._EditNote import EditNote
from Selectors import selector_factory
from DdTargets import DdTargets
class ObjEntry:
"""
Handles the selection of a existing or new Object. Supports Drag and Drop
to select the object.
This is the base class to create a real entry
"""
def __init__(self, dbstate, uistate, track, label, set_val,
get_val, add_edt, share):
"""Pass the dbstate and uistate and present track.
label is a gtk.Label that shows the persent value
set_val is function that is called when handle changes, use it
to update the calling module
get_val is function that is called to obtain handle from calling
module
share is the gtk.Button to call the object selector or del connect
add_edt is the gtk.Button with add or edit value. Pass None if
this button should not be present.
"""
self.label = label
self.add_edt = add_edt
self.share = share
self.dbstate = dbstate
self.db = dbstate.db
self.get_val = get_val
self.set_val = set_val
self.uistate = uistate
self.track = track
self.tooltips = gtk.Tooltips()
#connect drag and drop
self._init_dnd()
#set the object specific code
self._init_object()
#check if valid object:
handle = self.get_val()
if handle:
obj = self.get_from_handle(handle)
if not obj:
#invalid val, set it to None
self.set_val(None)
if self.get_val():
self.set_button(True)
obj = self.get_from_handle(self.get_val())
name = self.get_label(obj)
else:
name = u""
self.set_button(False)
if self.db.readonly:
if self.add_edt is not None:
self.add_edt.set_sensitive(False)
self.share.set_sensitive(False)
else:
if self.add_edt is not None:
self.add_edt.set_sensitive(True)
self.share.set_sensitive(True)
if self.add_edt is not None:
self.add_edt.connect('clicked', self.add_edt_clicked)
self.share.connect('clicked', self.share_clicked)
if not self.db.readonly and not name:
if self.add_edt is None:
self.label.set_text(self.EMPTY_TEXT_RED)
else:
self.label.set_text(self.EMPTY_TEXT)
self.label.set_use_markup(True)
else:
self.label.set_text(name)
def _init_dnd(self):
"""inheriting objects must set this
"""
pass
def _init_object(self):
"""inheriting objects can use this to set extra variables
"""
pass
def get_from_handle(self, handle):
""" return the object given the hande
inheriting objects must set this
"""
pass
def get_label(self, object):
""" return the label
inheriting objects must set this
"""
pass
def after_edit(self, obj):
name = self.get_label(obj)
self.label.set_text(name)
def add_edt_clicked(self, obj):
""" if value, edit, if no value, call editor on new object
"""
if self.get_val():
obj = self.get_from_handle(self.get_val())
self.call_editor(obj)
else:
self.call_editor()
def call_editor(self, obj):
"""inheriting objects must set this
"""
pass
def call_selector(self):
"""inheriting objects must set this
"""
pass
def drag_data_received(self, widget, context, x, y, selection, info, time):
(drag_type, idval, obj, val) = pickle.loads(selection.data)
data = self.db.get_place_from_handle(obj)
self.obj_added(data)
def obj_added(self, data):
""" callback from adding an object to the entry"""
self.set_val(data.handle)
self.label.set_text(self.get_label(data))
self.set_button(True)
def share_clicked(self, obj):
""" if value, delete connect, in no value, select existing object
"""
if self.get_val():
self.set_val(None)
self.label.set_text(self.EMPTY_TEXT)
self.label.set_use_markup(True)
self.set_button(False)
else:
select = self.call_selector()
obj = select.run()
if obj:
self.obj_added(obj)
def set_button(self, use_add):
""" This sets the correct image to the two buttons.
If False: select icon and add icon
If True: remove icon and edit icon
"""
if self.add_edt is not None:
for i in self.add_edt.get_children():
self.add_edt.remove(i)
for i in self.share.get_children():
self.share.remove(i)
if use_add:
image = gtk.Image()
image.set_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_BUTTON)
image.show()
self.share.add(image)
self.tooltips.set_tip(self.share, self.DEL_STR)
if self.add_edt is not None:
image = gtk.Image()
image.set_from_stock(gtk.STOCK_EDIT, gtk.ICON_SIZE_BUTTON)
image.show()
self.add_edt.add(image)
self.tooltips.set_tip(self.add_edt, self.EDIT_STR)
else:
image = gtk.Image()
image.set_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
image.show()
self.share.add(image)
self.tooltips.set_tip(self.share, self.SHARE_STR)
if self.add_edt is not None:
image = gtk.Image()
image.set_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_BUTTON)
image.show()
self.add_edt.add(image)
self.tooltips.set_tip(self.add_edt, self.ADD_STR)
class PlaceEntry(ObjEntry):
"""
Handles the selection of a existing or new Place. Supports Drag and Drop
to select a place.
"""
EMPTY_TEXT = "<i>%s</i>" % _('To select a place, use drag-and-drop '
'or use the buttons')
EMPTY_TEXT_RED = "<i>%s</i>" % _('No place given, click button to select one')
EDIT_STR = _('Edit place')
SHARE_STR = _('Select an existing place')
ADD_STR = _('Add a new place')
DEL_STR = _('Remove place')
def __init__(self, dbstate, uistate, track, label, set_val,
get_val, add_edt, share):
ObjEntry.__init__(self, dbstate, uistate, track, label, set_val,
get_val, add_edt, share)
def _init_dnd(self):
"""connect drag and drop of places
"""
self.label.drag_dest_set(gtk.DEST_DEFAULT_ALL, [DdTargets.PLACE_LINK.target()],
gtk.gdk.ACTION_COPY)
self.label.connect('drag_data_received', self.drag_data_received)
def get_from_handle(self, handle):
""" return the object given the hande
"""
return self.db.get_place_from_handle(handle)
def get_label(self, place):
return "%s [%s]" % (place.get_title(), place.gramps_id)
def call_editor(self, obj=None):
if obj is None:
place = Place()
func = self.obj_added
else:
place = obj
func = self.after_edit
try:
EditPlace(self.dbstate, self.uistate, self.track,
place, func)
except WindowActiveError:
pass
def call_selector(self):
cls = selector_factory('Place')
return cls(self.dbstate, self.uistate, self.track)
# FIXME isn't used anywhere
class MediaEntry(ObjEntry):
"""
Handles the selection of a existing or new media. Supports Drag and Drop
to select a media object.
"""
EMPTY_TEXT = "<i>%s</i>" % _('To select a media object, use drag-and-drop '
'or use the buttons')
EMPTY_TEXT_RED = "<i>%s</i>" % _('No image given, click button to select one')
EDIT_STR = _('Edit media object')
SHARE_STR = _('Select an existing media object')
ADD_STR = _('Add a new media object')
DEL_STR = _('Remove media object')
def __init__(self, dbstate, uistate, track, label, set_val,
get_val, add_edt, share):
ObjEntry.__init__(self, dbstate, uistate, track, label, set_val,
get_val, add_edt, share)
def _init_dnd(self):
"""connect drag and drop of places
"""
self.label.drag_dest_set(gtk.DEST_DEFAULT_ALL, [DdTargets.MEDIAOBJ.target()],
gtk.gdk.ACTION_COPY)
self.label.connect('drag_data_received', self.drag_data_received)
def get_from_handle(self, handle):
""" return the object given the hande
"""
return self.db.get_object_from_handle(handle)
def get_label(self, object):
return "%s [%s]" % (object.get_description(), object.gramps_id)
def call_editor(self, obj=None):
if obj is None:
object = MediaObject()
func = self.obj_added
else:
object = obj
func = self.after_edit
try:
EditMedia(self.dbstate, self.uistate, self.track,
object, func)
except WindowActiveError:
pass
def call_selector(self):
from Selectors import selector_factory
cls = selector_factory('MediaObject')
return cls(self.dbstate, self.uistate, self.track)
# FIXME isn't used anywhere
class NoteEntry(ObjEntry):
"""
Handles the selection of a existing or new Note. Supports Drag and Drop
to select a Note.
"""
EMPTY_TEXT = "<i>%s</i>" % _('To select a note, use drag-and-drop '
'or use the buttons')
EMPTY_TEXT_RED = "<i>%s</i>" % _('No note given, click button to select one')
EDIT_STR = _('Edit Note')
SHARE_STR = _('Select an existing note')
ADD_STR = _('Add a new note')
DEL_STR = _('Remove note')
def __init__(self, dbstate, uistate, track, label, set_val,
get_val, add_edt, share):
ObjEntry.__init__(self, dbstate, uistate, track, label, set_val,
get_val, add_edt, share)
self.notetype = None
def set_notetype(self, type):
""" set a notetype to use in new notes
"""
self.notetype = type
def get_notetype(self):
""" return the set notetype
"""
return self.notetype
def _init_dnd(self):
"""connect drag and drop of places
"""
self.label.drag_dest_set(gtk.DEST_DEFAULT_ALL, [DdTargets.NOTE_LINK.target()],
gtk.gdk.ACTION_COPY)
self.label.connect('drag_data_received', self.drag_data_received)
def get_from_handle(self, handle):
""" return the object given the hande
"""
return self.db.get_note_from_handle(handle)
def get_label(self, note):
txt = " ".join(note.get().split())
if len(txt) > 35:
txt = txt[:35]+"..."
else:
txt = txt
return "%s [%s]" % (txt, note.gramps_id)
def call_editor(self, obj=None):
if obj is None:
note = Note()
note.set_type(self.get_notetype())
func = self.obj_added
else:
note = obj
func = self.after_edit
try:
EditNote(self.dbstate, self.uistate, self.track,
note, func)
except WindowActiveError:
pass
def call_selector(self):
cls = selector_factory('Note')
return cls(self.dbstate, self.uistate, self.track)

View File

@ -7,11 +7,19 @@ pkgdatadir = $(datadir)/@PACKAGE@/widgets
pkgdata_PYTHON = \
__init__.py \
buttons.py \
expandcollapsearrow.py \
grampswidgets.py \
labels.py \
linkbox.py \
monitoredwidgets.py \
multitypecomboentry.py \
toolbarwidgets.py \
statusbar.py \
styledtextbuffer.py \
styledtexteditor.py
styledtexteditor.py \
toolbarwidgets.py \
unused.py \
validatedmaskedentry.py
pkgpyexecdir = @pkgpyexecdir@/widgets
pkgpythondir = @pkgpythondir@/widgets
@ -24,3 +32,4 @@ GRAMPS_PY_MODPATH = "../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));

View File

@ -22,12 +22,22 @@
"""Custom widgets."""
from grampswidgets import *
from monitoredwidgets import *
from labels import *
from buttons import *
from expandcollapsearrow import ExpandCollapseArrow
from linkbox import LinkBox
from statusbar import Statusbar
from validatedmaskedentry import ValidatableMaskedEntry
from multitypecomboentry import MultiTypeComboEntry
from toolbarwidgets import *
from styledtextbuffer import *
from styledtexteditor import *
# moved to src/ because of circular dependency
#from objectentries import *
from unused import *
# Enabling custom widgets to be included in Glade
from gtk.glade import set_custom_handler
def get_custom_handler(glade, function_name, widget_name,

154
src/widgets/buttons.py Normal file
View File

@ -0,0 +1,154 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2007-2008 The Gramps Developers
#
# 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.buttons")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
# STOCK_INFO was added only in Gtk 2.8
try:
INFO_ICON = gtk.STOCK_INFO
except AttributeError:
INFO_ICON = gtk.STOCK_DIALOG_INFO
#-------------------------------------------------------------------------
#
# IconButton class
#
#-------------------------------------------------------------------------
class IconButton(gtk.Button):
def __init__(self, func, handle, icon=gtk.STOCK_EDIT,
size=gtk.ICON_SIZE_MENU):
gtk.Button.__init__(self)
image = gtk.Image()
image.set_from_stock(icon, size)
image.show()
self.add(image)
self.set_relief(gtk.RELIEF_NONE)
self.show()
if func:
self.connect('button-press-event', func, handle)
self.connect('key-press-event', func, handle)
#-------------------------------------------------------------------------
#
# WarnButton class
#
#-------------------------------------------------------------------------
class WarnButton(gtk.Button):
def __init__(self):
gtk.Button.__init__(self)
image = gtk.Image()
image.set_from_stock(INFO_ICON, gtk.ICON_SIZE_MENU)
image.show()
self.add(image)
self.set_relief(gtk.RELIEF_NONE)
self.show()
self.func = None
self.hide()
def on_clicked(self, func):
self.connect('button-press-event', self._button_press)
self.func = func
def _button_press(self, obj, event):
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1:
self.func(obj)
#-------------------------------------------------------------------------
#
# SimpleButton class
#
#-------------------------------------------------------------------------
class SimpleButton(gtk.Button):
def __init__(self, image, func):
gtk.Button.__init__(self)
self.set_relief(gtk.RELIEF_NONE)
self.add(gtk.image_new_from_stock(image, gtk.ICON_SIZE_BUTTON))
self.connect('clicked', func)
self.show()
#-------------------------------------------------------------------------
#
# PrivacyButton class
#
#-------------------------------------------------------------------------
class PrivacyButton:
def __init__(self, button, obj, readonly=False):
self.button = button
self.button.connect('toggled', self._on_toggle)
self.tooltips = gtk.Tooltips()
self.obj = obj
self.set_active(obj.get_privacy())
self.button.set_sensitive(not readonly)
def set_sensitive(self, val):
self.button.set_sensitive(val)
def set_active(self, val):
self.button.set_active(val)
self._on_toggle(self.button)
def get_active(self):
return self.button.get_active()
def _on_toggle(self, obj):
child = obj.child
if child:
obj.remove(child)
image = gtk.Image()
if obj.get_active():
# image.set_from_icon_name('stock_lock', gtk.ICON_SIZE_MENU)
image.set_from_stock('gramps-lock', gtk.ICON_SIZE_MENU)
self.tooltips.set_tip(obj, _('Record is private'))
self.obj.set_privacy(True)
else:
# image.set_from_icon_name('stock_lock-open', gtk.ICON_SIZE_MENU)
image.set_from_stock('gramps-unlock', gtk.ICON_SIZE_MENU)
self.tooltips.set_tip(obj, _('Record is public'))
self.obj.set_privacy(False)
image.show()
obj.add(image)

View File

@ -0,0 +1,87 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2007-2008 The Gramps Developers
#
# 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
#
#-------------------------------------------------------------------------
from gettext import gettext as _
import logging
_LOG = logging.getLogger(".widgets.expandcollapsearrow")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
HAND_CURSOR = gtk.gdk.Cursor(gtk.gdk.HAND2)
#-------------------------------------------------------------------------
#
# Module functions
#
#-------------------------------------------------------------------------
def realize_cb(widget):
widget.window.set_cursor(HAND_CURSOR)
#-------------------------------------------------------------------------
#
# ExpandCollapseArrow class
#
#-------------------------------------------------------------------------
class ExpandCollapseArrow(gtk.EventBox):
"""
Arrow to be used for expand/collapse of sections.
Note: shadow does not work, we indicate action with realize_cb
"""
def __init__(self, collapsed, onbuttonpress, pair):
"""
Constructor for the ExpandCollapseArrow class.
@param collapsed: True if arrow must be shown collapsed,
False otherwise
@type collapsed: bool
@param onbuttonpress: The callback function for button press
@type onbuttonpress: callback
@param pair: user param for onbuttonpress function
"""
gtk.EventBox.__init__(self)
self.tooltips = gtk.Tooltips()
if collapsed :
self.arrow = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_OUT)
self.tooltips.set_tip(self, _("Expand this section"))
else:
self.arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_OUT)
self.tooltips.set_tip(self, _("Collapse this section"))
self.add(self.arrow)
self.connect('button-press-event', onbuttonpress, pair)
self.connect('realize', realize_cb)

205
src/widgets/labels.py Normal file
View File

@ -0,0 +1,205 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2007-2008 The Gramps Developers
#
# 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 os
import cgi
import logging
_LOG = logging.getLogger(".widgets.objectentries")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
import pango
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
import Config
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
HAND_CURSOR = gtk.gdk.Cursor(gtk.gdk.HAND2)
#-------------------------------------------------------------------------
#
# Module functions
#
#-------------------------------------------------------------------------
def realize_cb(widget):
widget.window.set_cursor(HAND_CURSOR)
#-------------------------------------------------------------------------
#
# LinkLabel class
#
#-------------------------------------------------------------------------
class LinkLabel(gtk.EventBox):
def __init__(self, label, func, handle, decoration=None):
if decoration == None:
relation_display_theme = Config.get(Config.RELATION_DISPLAY_THEME)
if relation_display_theme == "CLASSIC":
decoration = 'underline="single"'
elif relation_display_theme == "WEBPAGE":
decoration = 'foreground="blue"'
else:
raise AttributeError("invalid relation-display-theme: '%s'" % relation_display_theme)
gtk.EventBox.__init__(self)
self.orig_text = cgi.escape(label[0])
self.gender = label[1]
self.tooltips = gtk.Tooltips()
self.decoration = decoration
text = '<span %s>%s</span>' % (self.decoration, self.orig_text)
if func:
msg = _('Click to make the active person\n'
'Right click to display the edit menu')
if not Config.get(Config.RELEDITBTN):
msg += "\n" + _('Edit icons can be enabled in the Preferences dialog')
self.tooltips.set_tip(self, msg)
self.label = gtk.Label(text)
self.label.set_use_markup(True)
self.label.set_alignment(0, 0.5)
hbox = gtk.HBox()
hbox.pack_start(self.label, False, False, 0)
if label[1]:
hbox.pack_start(GenderLabel(label[1]), False, False, 0)
hbox.set_spacing(4)
self.add(hbox)
if func:
self.connect('button-press-event', func, handle)
self.connect('enter-notify-event', self.enter_text, handle)
self.connect('leave-notify-event', self.leave_text, handle)
self.connect('realize', realize_cb)
def set_padding(self, x, y):
self.label.set_padding(x, y)
def enter_text(self, obj, event, handle):
relation_display_theme = Config.get(Config.RELATION_DISPLAY_THEME)
if relation_display_theme == "CLASSIC":
text = '<span foreground="blue" %s>%s</span>' % (self.decoration, self.orig_text)
elif relation_display_theme == "WEBPAGE":
text = '<span underline="single" %s>%s</span>' % (self.decoration, self.orig_text)
else:
raise AttributeError("invalid relation-display-theme: '%s'" % relation_display_theme)
self.label.set_text(text)
self.label.set_use_markup(True)
def leave_text(self, obj, event, handle):
text = '<span %s>%s</span>' % (self.decoration, self.orig_text)
self.label.set_text(text)
self.label.set_use_markup(True)
#-------------------------------------------------------------------------
#
# EditLabel class
#
#-------------------------------------------------------------------------
class EditLabel(gtk.HBox):
def __init__(self, text):
gtk.HBox.__init__(self)
label = BasicLabel(text)
self.pack_start(label, False)
self.pack_start(gtk.image_new_from_stock(gtk.STOCK_EDIT,
gtk.ICON_SIZE_MENU), False)
self.set_spacing(4)
self.show_all()
#-------------------------------------------------------------------------
#
# BasicLabel class
#
#-------------------------------------------------------------------------
class BasicLabel(gtk.Label):
def __init__(self, text):
gtk.Label.__init__(self, text)
self.set_alignment(0, 0.5)
self.show()
#-------------------------------------------------------------------------
#
# GenderLabel class
#
#-------------------------------------------------------------------------
class GenderLabel(gtk.Label):
def __init__(self, text):
gtk.Label.__init__(self, text)
self.set_alignment(0, 0.5)
if os.sys.platform == "win32":
pangoFont = pango.FontDescription('Arial')
self.modify_font(pangoFont)
self.show()
#-------------------------------------------------------------------------
#
# MarkupLabel class
#
#-------------------------------------------------------------------------
class MarkupLabel(gtk.Label):
def __init__(self, text, x_align=0, y_align=0.5):
gtk.Label.__init__(self, text)
self.set_alignment(x_align, y_align)
self.set_use_markup(True)
self.show_all()
#-------------------------------------------------------------------------
#
# DualMarkupLabel class
#
#-------------------------------------------------------------------------
class DualMarkupLabel(gtk.HBox):
def __init__(self, text, alt, x_align=0, y_align=0.5):
gtk.HBox.__init__(self)
label = gtk.Label(text)
label.set_alignment(x_align, y_align)
label.set_use_markup(True)
self.pack_start(label, False, False, 0)
b = GenderLabel(alt)
b.set_use_markup(True)
self.pack_start(b, False, False, 4)
self.show()

52
src/widgets/linkbox.py Normal file
View File

@ -0,0 +1,52 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2007-2008 The Gramps Developers
#
# 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.linkbox")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# LinkBox class
#
#-------------------------------------------------------------------------
class LinkBox(gtk.HBox):
def __init__(self, link, button):
gtk.HBox.__init__(self)
self.set_spacing(6)
self.pack_start(link, False)
if button:
self.pack_start(button, False)
self.show()

View File

@ -0,0 +1,478 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2007-2008 The Gramps Developers
#
# 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)

260
src/widgets/statusbar.py Normal file
View File

@ -0,0 +1,260 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2007-2008 The Gramps Developers
#
# 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.statusbar")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gobject
import gtk
import pango
#-------------------------------------------------------------------------
#
# Statusbar class
#
#-------------------------------------------------------------------------
class Statusbar(gtk.HBox):
"""Custom Statusbar with flexible number of "bars".
Statusbar can have any number of fields included, each identified
by it's own bar id. It has by default one field with id = 0. This
defult field is used when no bar id is given in the relevant (push, pop,
etc.) methods, thus Statusbar behaves as a single gtk.Statusbar.
To add a new field use the "insert" method. Using the received bar id
one can push, pop and remove messages to/from this newly inserted field.
"""
__gtype_name__ = 'Statusbar'
##__gsignals__ = {
##'text-popped': ,
##'text-pushed': ,
##}
__gproperties__ = {
'has-resize-grip': (gobject.TYPE_BOOLEAN,
'Resize grip',
'Whether resize grip is visible',
True,
gobject.PARAM_READWRITE),
}
def __init__(self, min_width=30):
gtk.HBox.__init__(self)
# initialize pixel/character scale
pl = pango.Layout(self.get_pango_context())
pl.set_text("M")
(self._char_width, h) = pl.get_pixel_size()
# initialize property values
self.__has_resize_grip = True
# create the main statusbar with id #0
main_bar = gtk.Statusbar()
main_bar.set_size_request(min_width*self._char_width, -1)
main_bar.show()
self.pack_start(main_bar)
self._bars = {0: main_bar}
self._set_resize_grip()
# Virtual methods
def do_get_property(self, prop):
"""Return the gproperty's value.
"""
if prop.name == 'has-resize-grip':
return self.__has_resize_grip
else:
raise AttributeError, 'unknown property %s' % prop.name
def do_set_property(self, prop, value):
"""Set the property of writable properties.
"""
if prop.name == 'has-resize-grip':
self.__has_resize_grip = value
self._set_resize_grip()
else:
raise AttributeError, 'unknown or read only property %s' % prop.name
# Private
def _set_resize_grip(self):
"""Set the resize grip for the statusbar.
Resize grip is disabled for all statusbars except the last one,
which is set according to the "has-resize-grip" propery.
"""
for bar in self.get_children():
bar.set_has_resize_grip(False)
bar.set_has_resize_grip(self.get_property('has-resize-grip'))
def _set_packing(self):
"""Set packing style of the statusbars.
All bars are packed with "expand"=True, "fill"=True parameters,
except the last one, which is packed with "expand"=False, "fill"=False.
"""
for bar in self.get_children():
self.set_child_packing(bar, True, True, 0, gtk.PACK_START)
self.set_child_packing(bar, False, False, 0, gtk.PACK_START)
def _get_next_id(self):
"""Get next unused statusbar id.
"""
id = 1
while id in self._bars.keys():
id = id + 1
return id
# Public API
def insert(self, index=-1, min_width=30, ralign=False):
"""Insert a new statusbar.
Create a new statusbar and insert it at the given index. Index starts
from '0'. If index is negative the new statusbar is appended.
The new bar_id is returned.
"""
new_bar = gtk.Statusbar()
new_bar.set_size_request(min_width*self._char_width, -1)
new_bar.show()
self.pack_start(new_bar)
self.reorder_child(new_bar, index)
self._set_resize_grip()
self._set_packing()
if ralign:
label = new_bar.get_children()[0].get_children()[0]
label.set_alignment(xalign=1.0, yalign=0.5)
new_bar_id = self._get_next_id()
self._bars[new_bar_id] = new_bar
return new_bar_id
def get_context_id(self, context_description, bar_id=0):
"""Return a new or existing context identifier.
The target statusbar is identified by bar_id created when statusbar
was added.
Existence of the bar_id is not checked as giving a wrong id is
programming fault.
"""
return self._bars[bar_id].get_context_id(context_description)
def push(self, context_id, text, bar_id=0):
"""Push message onto a statusbar's stack.
The target statusbar is identified by bar_id created when statusbar
was added.
Existence of the bar_id is not checked as giving a wrong id is
programming fault.
"""
return self._bars[bar_id].push(context_id, text)
def pop(self, context_id, bar_id=0):
"""Remove the top message from a statusbar's stack.
The target statusbar is identified by bar_id created when statusbar
was added.
Existence of the bar_id is not checked as giving a wrong id is
programming fault.
"""
self._bars[bar_id].pop(context_id)
def remove(self, context_id, message_id, bar_id=0):
"""Remove the message with the specified message_id.
Remove the message with the specified message_id and context_id
from the statusbar's stack, which is identified by bar_id.
Existence of the bar_id is not checked as giving a wrong id is
programming fault.
"""
self._bars[bar_id].remove(context_id, message_id)
def set_has_resize_grip(self, setting):
"""Mirror gtk.Statusbar functionaliy.
"""
self.set_property('has-resize-grip', setting)
def get_has_resize_grip(self):
"""Mirror gtk.Statusbar functionaliy.
"""
return self.get_property('has-resize-grip')
def main(args):
win = gtk.Window()
win.set_title('Statusbar test window')
win.set_position(gtk.WIN_POS_CENTER)
def cb(window, event):
gtk.main_quit()
win.connect('delete-event', cb)
vbox = gtk.VBox()
win.add(vbox)
statusbar = Statusbar()
vbox.pack_end(statusbar, False)
statusbar.push(1, "This is my statusbar...")
my_statusbar = statusbar.insert(min_width=24)
statusbar.push(1, "Testing status bar width", my_statusbar)
yet_another_statusbar = statusbar.insert(1, 11)
statusbar.push(1, "A short one", yet_another_statusbar)
last_statusbar = statusbar.insert(min_width=41, ralign=True)
statusbar.push(1, "The last statusbar has always fixed width",
last_statusbar)
win.show_all()
gtk.main()
if __name__ == '__main__':
import sys
# fall back to root logger for testing
log = logging
sys.exit(main(sys.argv))

View File

@ -43,7 +43,7 @@ import gtk
# GRAMPS modules
#
#-------------------------------------------------------------------------
from widgets import MultiTypeComboEntry
from multitypecomboentry import MultiTypeComboEntry
#-------------------------------------------------------------------------
#

93
src/widgets/unused.py Normal file
View File

@ -0,0 +1,93 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2007-2008 The Gramps Developers
#
# 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.unused")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gobject
import gtk
#-------------------------------------------------------------------------
#
# IntEdit class
#
#-------------------------------------------------------------------------
# FIXME isn't used anywhere
class IntEdit(gtk.Entry):
"""An gtk.Edit widget that only allows integers."""
def __init__(self):
gtk.Entry.__init__(self)
self._signal = self.connect("insert_text", self.insert_cb)
def insert_cb(self, widget, text, length, *args):
# if you don't do this, garbage comes in with text
text = text[:length]
pos = widget.get_position()
# stop default emission
widget.emit_stop_by_name("insert_text")
gobject.idle_add(self.insert, widget, text, pos)
def insert(self, widget, text, pos):
if len(text) > 0 and text.isdigit():
# the next three lines set up the text. this is done because we
# can't use insert_text(): it always inserts at position zero.
orig_text = widget.get_text()
new_text = orig_text[:pos] + text + orig_text[pos:]
# avoid recursive calls triggered by set_text
widget.handler_block(self._signal)
# replace the text with some new text
widget.set_text(new_text)
widget.handler_unblock(self._signal)
# set the correct position in the widget
widget.set_position(pos + len(text))
#-------------------------------------------------------------------------
#
# TypeCellRenderer class
#
#-------------------------------------------------------------------------
# FIXME isn't used anywhere, though it is mentioned in _EditFamily.py
class TypeCellRenderer(gtk.CellRendererCombo):
def __init__(self, values):
gtk.CellRendererCombo.__init__(self)
model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT)
for key in values:
model.append(row=[values[key], key])
self.set_property('editable', True)
self.set_property('model', model)
self.set_property('text-column', 0)