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:
parent
75a04613be
commit
c6203b282b
@ -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)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
@ -38,4 +38,3 @@ from _EditSourceRef import *
|
||||
from _EditUrl import *
|
||||
from _EditPersonRef import *
|
||||
from _EditChildRef import *
|
||||
|
||||
|
@ -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
400
src/objectentries.py
Normal 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)
|
@ -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));
|
||||
|
||||
|
@ -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
154
src/widgets/buttons.py
Normal 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)
|
87
src/widgets/expandcollapsearrow.py
Normal file
87
src/widgets/expandcollapsearrow.py
Normal 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
205
src/widgets/labels.py
Normal 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
52
src/widgets/linkbox.py
Normal 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()
|
478
src/widgets/monitoredwidgets.py
Normal file
478
src/widgets/monitoredwidgets.py
Normal 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
260
src/widgets/statusbar.py
Normal 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))
|
@ -43,7 +43,7 @@ import gtk
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from widgets import MultiTypeComboEntry
|
||||
from multitypecomboentry import MultiTypeComboEntry
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
93
src/widgets/unused.py
Normal file
93
src/widgets/unused.py
Normal 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)
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user