move src/Editors/* to src/gui/editors as part of GEP008
svn: r13807
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
# If not using GNU make, then list all .py files individually
|
||||
|
||||
SUBDIRS = \
|
||||
editors \
|
||||
selectors \
|
||||
views \
|
||||
widgets
|
||||
|
||||
@@ -26,4 +26,4 @@ Package init for the gui package.
|
||||
|
||||
# DO NOT IMPORT METHODS/CLASSES FROM src/gui HERE ! Only __all__
|
||||
|
||||
__all__ = [ "views", "widgets" ]
|
||||
__all__ = [ "editors", "selectors", "views", "widgets" ]
|
||||
|
||||
46
src/gui/editors/Makefile.am
Normal file
46
src/gui/editors/Makefile.am
Normal file
@@ -0,0 +1,46 @@
|
||||
# This is the src/Editors level Makefile for Gramps
|
||||
# We could use GNU make's ':=' syntax for nice wildcard use,
|
||||
# but that is not necessarily portable.
|
||||
# If not using GNU make, then list all .py files individually
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/gui/editors
|
||||
|
||||
pkgdata_PYTHON = \
|
||||
addmedia.py\
|
||||
__init__.py\
|
||||
editaddress.py \
|
||||
editattribute.py \
|
||||
editchildRef.py \
|
||||
editevent.py \
|
||||
editeventRef.py \
|
||||
editfamily.py \
|
||||
editldsOrd.py \
|
||||
editlocation.py \
|
||||
editmedia.py \
|
||||
editmediaRef.py \
|
||||
editname.py \
|
||||
editnote.py \
|
||||
editperson.py \
|
||||
editpersonRef.py \
|
||||
editplace.py \
|
||||
editprimary.py \
|
||||
editreference.py \
|
||||
editrepository.py \
|
||||
editrepoRef.py \
|
||||
editsecondary.py \
|
||||
editsource.py \
|
||||
editsourceRef.py \
|
||||
editurl.py \
|
||||
objectentries.py
|
||||
|
||||
pkgpyexecdir = @pkgpyexecdir@/src/editors
|
||||
pkgpythondir = @pkgpythondir@/src/editors
|
||||
|
||||
# Clean up all the byte-compiled files
|
||||
MOSTLYCLEANFILES = *pyc *pyo
|
||||
|
||||
GRAMPS_PY_MODPATH = "../../"
|
||||
|
||||
pycheck:
|
||||
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
|
||||
pychecker $(pkgdata_PYTHON));
|
||||
40
src/gui/editors/__init__.py
Normal file
40
src/gui/editors/__init__.py
Normal file
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
from editaddress import EditAddress
|
||||
from editattribute import EditAttribute, EditFamilyAttribute
|
||||
from editchildref import EditChildRef
|
||||
from editevent import EditEvent, DeleteEventQuery
|
||||
from editeventref import EditEventRef
|
||||
from editfamily import EditFamily
|
||||
from editldsord import EditLdsOrd, EditFamilyLdsOrd
|
||||
from editlocation import EditLocation
|
||||
from editmedia import EditMedia, DeleteMediaQuery
|
||||
from editmediaref import EditMediaRef
|
||||
from editname import EditName
|
||||
from editnote import EditNote, DeleteNoteQuery
|
||||
from editperson import EditPerson
|
||||
from editpersonref import EditPersonRef
|
||||
from editplace import EditPlace, DeletePlaceQuery
|
||||
from editrepository import EditRepository, DeleteRepositoryQuery
|
||||
from editreporef import EditRepoRef
|
||||
from editsource import EditSource, DeleteSrcQuery
|
||||
from editsourceref import EditSourceRef
|
||||
from editurl import EditUrl
|
||||
236
src/gui/editors/addmedia.py
Normal file
236
src/gui/editors/addmedia.py
Normal file
@@ -0,0 +1,236 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
Provide the interface to allow a person to add a media object to the database.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import os
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# internationalization
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
import config
|
||||
import Utils
|
||||
import Mime
|
||||
import GrampsDisplay
|
||||
import ManagedWindow
|
||||
from QuestionDialog import ErrorDialog, WarningDialog
|
||||
from glade import Glade
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# AddMediaObject
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class AddMediaObject(ManagedWindow.ManagedWindow):
|
||||
"""
|
||||
Displays the Add Media Dialog window, allowing the user to select
|
||||
a file from the file system, while providing a description.
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate, uistate, track, mediaobj, callback=None):
|
||||
"""
|
||||
Create and displays the dialog box
|
||||
|
||||
db - the database in which the new object is to be stored
|
||||
The mediaobject is updated with the information, and on save, the
|
||||
callback function is called
|
||||
"""
|
||||
ManagedWindow.ManagedWindow.__init__(self, uistate, track, self)
|
||||
|
||||
self.dbase = dbstate.db
|
||||
self.obj = mediaobj
|
||||
self.callback = callback
|
||||
|
||||
self.last_directory = config.get('behavior.addmedia-image-dir')
|
||||
self.relative_path = config.get('behavior.addmedia-relative-path')
|
||||
|
||||
self.glade = Glade()
|
||||
self.set_window(
|
||||
self.glade.toplevel,
|
||||
self.glade.get_object('title'),
|
||||
_('Select a media object'))
|
||||
|
||||
self.description = self.glade.get_object("photoDescription")
|
||||
self.image = self.glade.get_object("image")
|
||||
self.file_text = self.glade.get_object("fname")
|
||||
if not(self.last_directory and os.path.isdir(self.last_directory)):
|
||||
self.last_directory = const.USER_HOME
|
||||
#if existing path, use dir of path
|
||||
if not self.obj.get_path() == "":
|
||||
fullname = Utils.media_path_full(self.dbase, self.obj.get_path())
|
||||
dir = os.path.dirname(fullname)
|
||||
if os.path.isdir(dir):
|
||||
self.last_directory = dir
|
||||
self.file_text.select_filename(fullname)
|
||||
else:
|
||||
self.file_text.set_current_folder(self.last_directory)
|
||||
else:
|
||||
self.file_text.set_current_folder(self.last_directory)
|
||||
if not self.obj.get_description() == "":
|
||||
self.description.set_text(self.obj.get_description())
|
||||
|
||||
self.relpath = self.glade.get_object('relpath')
|
||||
self.relpath.set_active(self.relative_path)
|
||||
self.temp_name = ""
|
||||
self.object = None
|
||||
|
||||
self.glade.get_object('fname').connect('update_preview',
|
||||
self.on_name_changed)
|
||||
self.ok_button = self.glade.get_object('button79')
|
||||
self.help_button = self.glade.get_object('button103')
|
||||
self.cancel_button = self.glade.get_object('button81')
|
||||
self.ok_button.connect('clicked', self.save)
|
||||
self.ok_button.set_sensitive(not self.dbase.readonly)
|
||||
self.help_button.connect('clicked', lambda x: GrampsDisplay.help())
|
||||
self.cancel_button.connect('clicked', self.close)
|
||||
self.show()
|
||||
self.modal_call()
|
||||
|
||||
def build_menu_names(self, obj):
|
||||
"""
|
||||
Build the menu name for the window manager.
|
||||
"""
|
||||
return(_('Select media object'), None)
|
||||
|
||||
def save(self, *obj):
|
||||
"""
|
||||
Callback function called when the save button is pressed.
|
||||
The media object is updated, and callback called.
|
||||
"""
|
||||
description = unicode(self.description.get_text())
|
||||
|
||||
if self.file_text.get_filename() is None:
|
||||
msgstr = _("Import failed")
|
||||
msgstr2 = _("The filename supplied could not be found.")
|
||||
ErrorDialog(msgstr, msgstr2)
|
||||
return
|
||||
|
||||
filename = Utils.get_unicode_path(self.file_text.get_filename())
|
||||
full_file = filename
|
||||
|
||||
if self.relpath.get_active():
|
||||
pname = unicode(Utils.media_path(self.dbase))
|
||||
if not os.path.exists(pname):
|
||||
msgstr = _("Cannot import %s")
|
||||
msgstr2 = _("Directory specified in preferences: Base path for relative media paths: %s does not exist. Change preferences or do not use relative path when importing")
|
||||
ErrorDialog(msgstr % filename, msgstr2 % pname)
|
||||
return
|
||||
filename = Utils.relative_path(filename, pname)
|
||||
|
||||
|
||||
mtype = Mime.get_type(full_file)
|
||||
description = description or os.path.basename(filename)
|
||||
|
||||
self.obj.set_description(description)
|
||||
self.obj.set_mime_type(mtype)
|
||||
name = filename
|
||||
self.obj.set_path(name)
|
||||
|
||||
self.last_directory = os.path.dirname(full_file)
|
||||
self.relative_path = self.relpath.get_active()
|
||||
|
||||
self._cleanup_on_exit()
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
|
||||
def on_name_changed(self, *obj):
|
||||
"""
|
||||
Called anytime the filename text window changes. Checks to
|
||||
see if the file exists. If it does, the image is loaded into
|
||||
the preview window.
|
||||
"""
|
||||
fname = self.file_text.get_filename()
|
||||
if not fname:
|
||||
return
|
||||
filename = Utils.get_unicode_path(fname)
|
||||
basename = os.path.basename(filename)
|
||||
(root, ext) = os.path.splitext(basename)
|
||||
old_title = unicode(self.description.get_text())
|
||||
|
||||
if old_title == '' or old_title == self.temp_name:
|
||||
self.description.set_text(root)
|
||||
self.temp_name = root
|
||||
|
||||
filename = Utils.find_file( filename)
|
||||
if filename:
|
||||
mtype = Mime.get_type(filename)
|
||||
if mtype and mtype.startswith("image"):
|
||||
image = scale_image(filename, const.THUMBSCALE)
|
||||
else:
|
||||
image = Mime.find_mime_type_pixbuf(mtype)
|
||||
self.image.set_from_pixbuf(image)
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
config.set('behavior.addmedia-image-dir', self.last_directory)
|
||||
config.set('behavior.addmedia-relative-path', self.relative_path)
|
||||
config.save()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# scale_image
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def scale_image(path, size):
|
||||
"""
|
||||
Scales the image to the specified size
|
||||
"""
|
||||
|
||||
title_msg = _("Cannot display %s") % path
|
||||
detail_msg = _('Gramps is not able to display the image file. '
|
||||
'This may be caused by a corrupt file.')
|
||||
|
||||
try:
|
||||
image1 = gtk.gdk.pixbuf_new_from_file(path)
|
||||
width = image1.get_width()
|
||||
height = image1.get_height()
|
||||
|
||||
scale = size / float(max(width, height))
|
||||
return image1.scale_simple(int(scale*width), int(scale*height),
|
||||
gtk.gdk.INTERP_BILINEAR)
|
||||
except:
|
||||
WarningDialog(title_msg, detail_msg)
|
||||
return gtk.gdk.pixbuf_new_from_file(const.ICON)
|
||||
|
||||
156
src/gui/editors/editaddress.py
Normal file
156
src/gui/editors/editaddress.py
Normal file
@@ -0,0 +1,156 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
"""
|
||||
The EditAddress module provides the EditAddress class. This provides a
|
||||
mechanism for the user to edit address information.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from editsecondary import EditSecondary
|
||||
from gen.lib import NoteType
|
||||
from glade import Glade
|
||||
from DisplayTabs import SourceEmbedList, NoteTab
|
||||
from gui.widgets import MonitoredDate, MonitoredEntry, PrivacyButton
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditAddress class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditAddress(EditSecondary):
|
||||
"""
|
||||
Displays a dialog that allows the user to edit an address.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, dbstate, uistate, track, addr, callback):
|
||||
"""
|
||||
Displays the dialog box.
|
||||
|
||||
parent - The class that called the Address editor.
|
||||
addr - The address that is to be edited
|
||||
"""
|
||||
EditSecondary.__init__(self, dbstate, uistate, track, addr, callback)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.address-width'
|
||||
self.height_key = 'interface.address-height'
|
||||
|
||||
self.top = Glade()
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object("title"),
|
||||
_('Address Editor'))
|
||||
|
||||
def _setup_fields(self):
|
||||
self.addr_start = MonitoredDate(
|
||||
self.top.get_object("date_entry"),
|
||||
self.top.get_object("date_stat"),
|
||||
self.obj.get_date_object(),
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.readonly)
|
||||
|
||||
self.street = MonitoredEntry(
|
||||
self.top.get_object("street"), self.obj.set_street,
|
||||
self.obj.get_street, self.db.readonly)
|
||||
|
||||
self.city = MonitoredEntry(
|
||||
self.top.get_object("city"), self.obj.set_city,
|
||||
self.obj.get_city, self.db.readonly)
|
||||
|
||||
self.state = MonitoredEntry(
|
||||
self.top.get_object("state"), self.obj.set_state,
|
||||
self.obj.get_state, self.db.readonly)
|
||||
|
||||
self.country = MonitoredEntry(
|
||||
self.top.get_object("country"), self.obj.set_country,
|
||||
self.obj.get_country, self.db.readonly)
|
||||
|
||||
self.postal = MonitoredEntry(
|
||||
self.top.get_object("postal"), self.obj.set_postal_code,
|
||||
self.obj.get_postal_code, self.db.readonly)
|
||||
|
||||
self.phone = MonitoredEntry(
|
||||
self.top.get_object("phone"), self.obj.set_phone,
|
||||
self.obj.get_phone, self.db.readonly)
|
||||
|
||||
self.priv = PrivacyButton(self.top.get_object("private"),
|
||||
self.obj, self.db.readonly)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_help_button(self.top.get_object('help'))
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
self.define_ok_button(self.top.get_object('ok'),self.save)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
Create the notebook tabs and inserts them into the main
|
||||
window.
|
||||
"""
|
||||
|
||||
notebook = gtk.Notebook()
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=NoteType.ADDRESS))
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
notebook.show_all()
|
||||
self.top.get_object('vbox').pack_start(notebook,True)
|
||||
|
||||
def build_menu_names(self, obj):
|
||||
return (_('Address'),_('Address Editor'))
|
||||
|
||||
def save(self,*obj):
|
||||
"""
|
||||
Called when the OK button is pressed. Gets data from the
|
||||
form and updates the Address data structure.
|
||||
"""
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
170
src/gui/editors/editattribute.py
Normal file
170
src/gui/editors/editattribute.py
Normal file
@@ -0,0 +1,170 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
"""
|
||||
The EditAttribute module provides the AttributeEditor class. This provides a
|
||||
mechanism for the user to edit attribute information.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from editsecondary import EditSecondary
|
||||
from gen.lib import NoteType
|
||||
from glade import Glade
|
||||
from DisplayTabs import SourceEmbedList, NoteTab
|
||||
from gui.widgets import MonitoredEntry, PrivacyButton, MonitoredDataType
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditAttribute class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditAttribute(EditSecondary):
|
||||
"""
|
||||
Displays a dialog that allows the user to edit an attribute.
|
||||
"""
|
||||
|
||||
def __init__(self, state, uistate, track, attrib, title, data_list, callback):
|
||||
"""
|
||||
Displays the dialog box.
|
||||
|
||||
parent - The class that called the Address editor.
|
||||
attrib - The attribute that is to be edited
|
||||
title - The title of the dialog box
|
||||
list - list of options for the pop down menu
|
||||
"""
|
||||
self.alist = data_list
|
||||
EditSecondary.__init__(self, state, uistate, track, attrib, callback)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.attribute-width'
|
||||
self.height_key = 'interface.attribute-height'
|
||||
self.top = Glade()
|
||||
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object('title'),
|
||||
_('Attribute Editor'))
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
self.define_help_button(self.top.get_object('help'))
|
||||
self.define_ok_button(self.top.get_object('ok'),self.save)
|
||||
|
||||
def _setup_fields(self):
|
||||
self.value_field = MonitoredEntry(
|
||||
self.top.get_object("attr_value"),
|
||||
self.obj.set_value, self.obj.get_value,
|
||||
self.db.readonly)
|
||||
|
||||
self.priv = PrivacyButton(
|
||||
self.top.get_object("private"),
|
||||
self.obj, self.db.readonly)
|
||||
|
||||
self.type_selector = MonitoredDataType(
|
||||
self.top.get_object("attr_menu"),
|
||||
self.obj.set_type,
|
||||
self.obj.get_type,
|
||||
self.db.readonly,
|
||||
custom_values=self.alist
|
||||
)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
notebook = gtk.Notebook()
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype = NoteType.ATTRIBUTE))
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
notebook.show_all()
|
||||
self.top.get_object('vbox').pack_start(notebook,True)
|
||||
|
||||
def build_menu_names(self, attrib):
|
||||
if not attrib:
|
||||
label = _("New Attribute")
|
||||
else:
|
||||
label = str(attrib.get_type())
|
||||
if not label.strip():
|
||||
label = _("New Attribute")
|
||||
label = "%s: %s" % (_('Attribute'),label)
|
||||
return (label, _('Attribute Editor'))
|
||||
|
||||
def save(self,*obj):
|
||||
"""
|
||||
Called when the OK button is pressed. Gets data from the
|
||||
form and updates the Attribute data structure.
|
||||
"""
|
||||
t = self.obj.get_type()
|
||||
|
||||
if t.is_custom() and str(t) == '':
|
||||
from QuestionDialog import ErrorDialog
|
||||
ErrorDialog(
|
||||
_("Cannot save attribute"),
|
||||
_("The attribute type cannot be empty"))
|
||||
return
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditAttribute class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditFamilyAttribute(EditAttribute):
|
||||
"""
|
||||
Displays a dialog that allows the user to edit an attribute.
|
||||
"""
|
||||
def __init__(self, state, uistate, track, attrib, title, data_list, callback):
|
||||
"""
|
||||
Displays the dialog box.
|
||||
|
||||
parent - The class that called the Address editor.
|
||||
attrib - The attribute that is to be edited
|
||||
title - The title of the dialog box
|
||||
list - list of options for the pop down menu
|
||||
"""
|
||||
EditAttribute.__init__(self, state, uistate, track, attrib, title,
|
||||
data_list, callback)
|
||||
211
src/gui/editors/editchildref.py
Normal file
211
src/gui/editors/editchildref.py
Normal file
@@ -0,0 +1,211 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
"""
|
||||
The EditChildRef module provides the EditChildRef class. This provides a
|
||||
mechanism for the user to edit address information.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from editsecondary import EditSecondary
|
||||
from gen.lib import NoteType
|
||||
import Errors
|
||||
from glade import Glade
|
||||
from DisplayTabs import SourceEmbedList, NoteTab
|
||||
from gui.widgets import MonitoredDataType, PrivacyButton
|
||||
from BasicUtils import name_displayer
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
_RETURN = gtk.gdk.keyval_from_name("Return")
|
||||
_KP_ENTER = gtk.gdk.keyval_from_name("KP_Enter")
|
||||
_LEFT_BUTTON = 1
|
||||
_RIGHT_BUTTON = 3
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditChildRef class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditChildRef(EditSecondary):
|
||||
"""
|
||||
Displays a dialog that allows the user to edit an address.
|
||||
"""
|
||||
def __init__(self, name, dbstate, uistate, track, childref, callback):
|
||||
"""
|
||||
Displays the dialog box.
|
||||
|
||||
parent - The class that called the ChildRef editor.
|
||||
addr - The address that is to be edited
|
||||
"""
|
||||
self.name = name
|
||||
EditSecondary.__init__(self, dbstate, uistate, track,
|
||||
childref, callback)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.child-ref-width'
|
||||
self.height_key = 'interface.child-ref-height'
|
||||
|
||||
self.top = Glade()
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object("title"),
|
||||
self.name,
|
||||
_('Child Reference Editor'))
|
||||
|
||||
self.ok_button = self.top.get_object('ok')
|
||||
self.edit_button = self.top.get_object('edit')
|
||||
self.name_label = self.top.get_object('name')
|
||||
self.name_label.set_text(self.name)
|
||||
|
||||
def _setup_fields(self):
|
||||
self.frel = MonitoredDataType(
|
||||
self.top.get_object('frel'),
|
||||
self.obj.set_father_relation,
|
||||
self.obj.get_father_relation,
|
||||
self.db.readonly,
|
||||
self.db.get_child_reference_types()
|
||||
)
|
||||
|
||||
self.mrel = MonitoredDataType(
|
||||
self.top.get_object('mrel'),
|
||||
self.obj.set_mother_relation,
|
||||
self.obj.get_mother_relation,
|
||||
self.db.readonly,
|
||||
self.db.get_child_reference_types()
|
||||
)
|
||||
|
||||
self.priv = PrivacyButton(
|
||||
self.top.get_object("private"),
|
||||
self.obj,
|
||||
self.db.readonly)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_help_button(self.top.get_object('help'))
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
self.define_ok_button(self.ok_button, self.save)
|
||||
self.edit_button.connect('button-press-event', self.edit_child)
|
||||
self.edit_button.connect('key-press-event', self.edit_child)
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('person-update', self.person_change)
|
||||
self._add_db_signal('person-rebuild', self.close)
|
||||
self._add_db_signal('person-delete', self.check_for_close)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
Create the notebook tabs and inserts them into the main
|
||||
window.
|
||||
"""
|
||||
notebook = gtk.Notebook()
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=NoteType.CHILDREF))
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
notebook.show_all()
|
||||
self.top.get_object('vbox').pack_start(notebook,True)
|
||||
|
||||
def _post_init(self):
|
||||
self.ok_button.grab_focus()
|
||||
|
||||
def build_menu_names(self, obj):
|
||||
return (_('Child Reference'),_('Child Reference Editor'))
|
||||
|
||||
def edit_child(self, obj,event):
|
||||
if button_activated(event, _LEFT_BUTTON):
|
||||
from _EditPerson import EditPerson
|
||||
handle = self.obj.ref
|
||||
try:
|
||||
person = self.db.get_person_from_handle(handle)
|
||||
EditPerson(self.dbstate, self.uistate,
|
||||
self.track, person)
|
||||
except Errors.WindowActiveError:
|
||||
pass
|
||||
|
||||
def person_change(self, handles):
|
||||
# check to see if the handle matches the current object
|
||||
if self.obj.ref in handles:
|
||||
p = self.dbstate.db.get_person_from_handle(self.obj.ref)
|
||||
self.name = name_displayer.display(p)
|
||||
self.name_label.set_text(self.name)
|
||||
|
||||
def save(self,*obj):
|
||||
"""
|
||||
Called when the OK button is pressed. Gets data from the
|
||||
form and updates the ChildRef data structure.
|
||||
"""
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
|
||||
def check_for_close(self, handles):
|
||||
"""
|
||||
Callback method for delete signals.
|
||||
If there is a delete signal of the primary object we are editing, the
|
||||
editor (and all child windows spawned) should be closed
|
||||
"""
|
||||
if self.obj.ref in handles:
|
||||
self.close()
|
||||
|
||||
def button_activated(event, mouse_button):
|
||||
if (event.type == gtk.gdk.BUTTON_PRESS and \
|
||||
event.button == mouse_button) or \
|
||||
(event.type == gtk.gdk.KEY_PRESS and \
|
||||
event.keyval in (_RETURN, _KP_ENTER)):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
345
src/gui/editors/editevent.py
Normal file
345
src/gui/editors/editevent.py
Normal file
@@ -0,0 +1,345 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from TransUtils import sgettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
import gen.lib
|
||||
import GrampsDisplay
|
||||
from editprimary import EditPrimary
|
||||
from objectentries import PlaceEntry
|
||||
from glade import Glade
|
||||
from QuestionDialog import ErrorDialog
|
||||
from DisplayTabs import (SourceEmbedList, NoteTab, GalleryTab,
|
||||
EventBackRefList, AttrEmbedList)
|
||||
from gui.widgets import (MonitoredEntry, PrivacyButton,
|
||||
MonitoredDataType, MonitoredDate)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
WIKI_HELP_PAGE = '%s_-_Entering_and_Editing_Data:_Detailed_-_part_2' % const.URL_MANUAL_PAGE
|
||||
WIKI_HELP_SEC = _('manual|Editing_Information_About_Events')
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditEvent class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditEvent(EditPrimary):
|
||||
|
||||
def __init__(self, dbstate, uistate, track, event, callback=None):
|
||||
|
||||
EditPrimary.__init__(self, dbstate, uistate, track,
|
||||
event, dbstate.db.get_event_from_handle,
|
||||
dbstate.db.get_event_from_gramps_id)
|
||||
|
||||
self._init_event()
|
||||
|
||||
def _init_event(self):
|
||||
self.commit_event = self.db.commit_event
|
||||
|
||||
def empty_object(self):
|
||||
return gen.lib.Event()
|
||||
|
||||
def get_menu_title(self):
|
||||
if self.obj.get_handle():
|
||||
event_name = self.obj.get_description()
|
||||
if not event_name:
|
||||
event_name = str(self.obj.get_type())
|
||||
dialog_title = _('Event: %s') % event_name
|
||||
else:
|
||||
dialog_title = _('New Event')
|
||||
return dialog_title
|
||||
|
||||
def get_custom_events(self):
|
||||
return self.dbstate.db.get_person_event_types() + \
|
||||
self.dbstate.db.get_family_event_types()
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.event-width'
|
||||
self.height_key = 'interface.event-height'
|
||||
|
||||
self.top = Glade()
|
||||
self.set_window(self.top.toplevel, None,
|
||||
self.get_menu_title())
|
||||
|
||||
self.place = self.top.get_object('place')
|
||||
self.share_btn = self.top.get_object('select_place')
|
||||
self.add_del_btn = self.top.get_object('add_del_place')
|
||||
|
||||
def _connect_signals(self):
|
||||
self.top.get_object('button111').connect('clicked', self.close)
|
||||
self.top.get_object('button126').connect('clicked', self.help_clicked)
|
||||
|
||||
self.ok_button = self.top.get_object('ok')
|
||||
self.ok_button.set_sensitive(not self.db.readonly)
|
||||
self.ok_button.connect('clicked', self.save)
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('event-rebuild', self._do_close)
|
||||
self._add_db_signal('event-delete', self.check_for_close)
|
||||
|
||||
def _setup_fields(self):
|
||||
|
||||
# place, select_place, add_del_place
|
||||
|
||||
self.place_field = PlaceEntry(self.dbstate, self.uistate, self.track,
|
||||
self.top.get_object("place"),
|
||||
self.obj.set_place_handle,
|
||||
self.obj.get_place_handle,
|
||||
self.add_del_btn, self.share_btn)
|
||||
|
||||
self.descr_field = MonitoredEntry(self.top.get_object("event_description"),
|
||||
self.obj.set_description,
|
||||
self.obj.get_description,
|
||||
self.db.readonly)
|
||||
|
||||
self.gid = MonitoredEntry(self.top.get_object("gid"),
|
||||
self.obj.set_gramps_id,
|
||||
self.obj.get_gramps_id, self.db.readonly)
|
||||
|
||||
self.priv = PrivacyButton( self.top.get_object("private"),
|
||||
self.obj, self.db.readonly)
|
||||
|
||||
self.event_menu = MonitoredDataType(self.top.get_object("personal_events"),
|
||||
self.obj.set_type,
|
||||
self.obj.get_type,
|
||||
custom_values=self.get_custom_events())
|
||||
|
||||
self.date_field = MonitoredDate(self.top.get_object("date_entry"),
|
||||
self.top.get_object("date_stat"),
|
||||
self.obj.get_date_object(),
|
||||
self.uistate, self.track,
|
||||
self.db.readonly)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
Create the notebook tabs and inserts them into the main
|
||||
window.
|
||||
"""
|
||||
notebook = gtk.Notebook()
|
||||
|
||||
self.source_list = SourceEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj)
|
||||
self._add_tab(notebook, self.source_list)
|
||||
|
||||
self.note_list = NoteTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=gen.lib.NoteType.EVENT)
|
||||
self._add_tab(notebook, self.note_list)
|
||||
|
||||
|
||||
self.gallery_list = GalleryTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_media_list())
|
||||
self._add_tab(notebook, self.gallery_list)
|
||||
|
||||
self.attr_list = AttrEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_attribute_list())
|
||||
self._add_tab(notebook, self.attr_list)
|
||||
|
||||
handle_list = self.dbstate.db.find_backlink_handles(self.obj.handle)
|
||||
self.backref_list = EventBackRefList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
handle_list)
|
||||
self._add_tab(notebook, self.backref_list)
|
||||
|
||||
self._setup_notebook_tabs(notebook)
|
||||
|
||||
notebook.show_all()
|
||||
self.top.get_object('vbox').pack_start(notebook, True)
|
||||
|
||||
self.track_ref_for_deletion("source_list")
|
||||
self.track_ref_for_deletion("note_list")
|
||||
self.track_ref_for_deletion("gallery_list")
|
||||
self.track_ref_for_deletion("attr_list")
|
||||
self.track_ref_for_deletion("backref_list")
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
self.backref_list.close()
|
||||
|
||||
def build_menu_names(self, event):
|
||||
return (_('Edit Event'), self.get_menu_title())
|
||||
|
||||
def help_clicked(self, obj):
|
||||
"""Display the relevant portion of GRAMPS manual"""
|
||||
GrampsDisplay.help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)
|
||||
def save(self, *obj):
|
||||
self.ok_button.set_sensitive(False)
|
||||
if self.object_is_empty():
|
||||
ErrorDialog(_("Cannot save event"),
|
||||
_("No data exists for this event. Please "
|
||||
"enter data or cancel the edit."))
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
(uses_dupe_id, id) = self._uses_duplicate_id()
|
||||
if uses_dupe_id:
|
||||
prim_object = self.get_from_gramps_id(id)
|
||||
name = prim_object.get_description()
|
||||
msg1 = _("Cannot save event. ID already exists.")
|
||||
msg2 = _("You have attempted to use the existing Gramps ID with "
|
||||
"value %(id)s. This value is already used by '"
|
||||
"%(prim_object)s'. Please enter a different ID or leave "
|
||||
"blank to get the next available ID value.") % {
|
||||
'id' : id, 'prim_object' : name }
|
||||
ErrorDialog(msg1, msg2)
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
t = self.obj.get_type()
|
||||
if t.is_custom() and str(t) == '':
|
||||
ErrorDialog(
|
||||
_("Cannot save event"),
|
||||
_("The event type cannot be empty"))
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
if not self.obj.handle:
|
||||
trans = self.db.transaction_begin()
|
||||
self.db.add_event(self.obj, trans)
|
||||
self.db.transaction_commit(trans, _("Add Event"))
|
||||
else:
|
||||
orig = self.get_from_handle(self.obj.handle)
|
||||
if cmp(self.obj.serialize(), orig.serialize()):
|
||||
trans = self.db.transaction_begin()
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_event_gramps_id())
|
||||
self.commit_event(self.obj, trans)
|
||||
self.db.transaction_commit(trans, _("Edit Event"))
|
||||
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
|
||||
def data_has_changed(self):
|
||||
"""
|
||||
A date comparison can fail incorrectly because we have made the
|
||||
decision to store entered text in the date. However, there is no
|
||||
entered date when importing from a XML file, so we can get an
|
||||
incorrect fail.
|
||||
"""
|
||||
|
||||
if self.db.readonly:
|
||||
return False
|
||||
elif self.obj.handle:
|
||||
orig = self.get_from_handle(self.obj.handle)
|
||||
if orig:
|
||||
cmp_obj = orig
|
||||
else:
|
||||
cmp_obj = self.empty_object()
|
||||
return cmp(cmp_obj.serialize(True)[1:],
|
||||
self.obj.serialize(True)[1:]) != 0
|
||||
else:
|
||||
cmp_obj = self.empty_object()
|
||||
return cmp(cmp_obj.serialize(True)[1:],
|
||||
self.obj.serialize()[1:]) != 0
|
||||
|
||||
|
||||
class EditPersonEvent(EditEvent):
|
||||
|
||||
def __init__(self, dbstate, uistate, track, event, callback=None):
|
||||
EditEvent.__init__(self, dbstate, uistate, track, event, callback)
|
||||
|
||||
def _init_event(self):
|
||||
self.commit_event = self.db.commit_personal_event
|
||||
|
||||
def get_custom_events(self):
|
||||
return self.dbstate.db.get_person_event_types()
|
||||
|
||||
class EditFamilyEvent(EditEvent):
|
||||
|
||||
def __init__(self, dbstate, uistate, track, event, callback=None):
|
||||
EditEvent.__init__(self, dbstate, uistate, track, event, callback)
|
||||
|
||||
def _init_event(self):
|
||||
self.commit_event = self.db.commit_family_event
|
||||
|
||||
def get_custom_events(self):
|
||||
return self.dbstate.db.get_family_event_types()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Delete Query class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class DeleteEventQuery(object):
|
||||
def __init__(self, dbstate, uistate, event, person_list, family_list):
|
||||
self.event = event
|
||||
self.db = dbstate.db
|
||||
self.uistate = uistate
|
||||
self.person_list = person_list
|
||||
self.family_list = family_list
|
||||
|
||||
def query_response(self):
|
||||
trans = self.db.transaction_begin()
|
||||
self.db.disable_signals()
|
||||
|
||||
ev_handle_list = [self.event.get_handle()]
|
||||
|
||||
for handle in self.person_list:
|
||||
person = self.db.get_person_from_handle(handle)
|
||||
person.remove_handle_references('Event', ev_handle_list)
|
||||
self.db.commit_person(person, trans)
|
||||
|
||||
for handle in self.family_list:
|
||||
family = self.db.get_family_from_handle(handle)
|
||||
family.remove_handle_references('Event', ev_handle_list)
|
||||
self.db.commit_family(family, trans)
|
||||
|
||||
self.db.enable_signals()
|
||||
self.db.remove_event(self.event.get_handle(), trans)
|
||||
self.db.transaction_commit(
|
||||
trans,_("Delete Event (%s)") % self.event.get_gramps_id())
|
||||
266
src/gui/editors/editeventref.py
Normal file
266
src/gui/editors/editeventref.py
Normal file
@@ -0,0 +1,266 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gen.lib
|
||||
from glade import Glade
|
||||
from DisplayTabs import (SourceEmbedList, NoteTab, GalleryTab,
|
||||
EventBackRefList, AttrEmbedList)
|
||||
from gui.widgets import (PrivacyButton, MonitoredEntry,
|
||||
MonitoredDate, MonitoredDataType)
|
||||
from editreference import RefTab, EditReference
|
||||
|
||||
from objectentries import PlaceEntry
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditEventRef class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditEventRef(EditReference):
|
||||
|
||||
def __init__(self, state, uistate, track, event, event_ref, update):
|
||||
EditReference.__init__(self, state, uistate, track, event, event_ref,
|
||||
update)
|
||||
self._init_event()
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.event-ref-width'
|
||||
self.height_key = 'interface.event-ref-height'
|
||||
|
||||
self.top = Glade()
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object('eer_title'),
|
||||
_('Event Reference Editor'))
|
||||
self.define_warn_box(self.top.get_object("eer_warning"))
|
||||
self.define_expander(self.top.get_object("eer_expander"))
|
||||
self.share_btn = self.top.get_object('share_place')
|
||||
self.add_del_btn = self.top.get_object('add_del_place')
|
||||
|
||||
tblref = self.top.get_object('table64')
|
||||
notebook = self.top.get_object('notebook_ref')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.reftab = RefTab(self.dbstate, self.uistate, self.track,
|
||||
_('General'), tblref)
|
||||
tblref = self.top.get_object('table62')
|
||||
notebook = self.top.get_object('notebook')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.primtab = RefTab(self.dbstate, self.uistate, self.track,
|
||||
_('_General'), tblref)
|
||||
|
||||
def _init_event(self):
|
||||
self.commit_event = self.db.commit_personal_event
|
||||
self.add_event = self.db.add_person_event
|
||||
|
||||
def get_custom_events(self):
|
||||
return self.db.get_person_event_types()
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_ok_button(self.top.get_object('ok'),self.ok_clicked)
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
# FIXME: activate when help page is available
|
||||
#self.define_help_button(self.top.get_object('help'))
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('event-rebuild', self.close)
|
||||
self._add_db_signal('event-delete', self.check_for_close)
|
||||
|
||||
def _setup_fields(self):
|
||||
|
||||
self.ref_privacy = PrivacyButton(
|
||||
self.top.get_object('eer_ref_priv'),
|
||||
self.source_ref, self.db.readonly)
|
||||
|
||||
self.descr_field = MonitoredEntry(
|
||||
self.top.get_object("eer_description"),
|
||||
self.source.set_description,
|
||||
self.source.get_description,
|
||||
self.db.readonly)
|
||||
|
||||
self.gid = MonitoredEntry(
|
||||
self.top.get_object("gid"),
|
||||
self.source.set_gramps_id,
|
||||
self.source.get_gramps_id,
|
||||
self.db.readonly)
|
||||
|
||||
self.place_field = PlaceEntry(
|
||||
self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.top.get_object("eer_place"),
|
||||
self.source.set_place_handle,
|
||||
self.source.get_place_handle,
|
||||
self.share_btn,
|
||||
self.add_del_btn)
|
||||
|
||||
self.ev_privacy = PrivacyButton(
|
||||
self.top.get_object("eer_ev_priv"),
|
||||
self.source, self.db.readonly)
|
||||
|
||||
self.role_selector = MonitoredDataType(
|
||||
self.top.get_object('eer_role_combo'),
|
||||
self.source_ref.set_role,
|
||||
self.source_ref.get_role,
|
||||
self.db.readonly,
|
||||
self.db.get_event_roles()
|
||||
)
|
||||
|
||||
self.event_menu = MonitoredDataType(
|
||||
self.top.get_object("eer_type_combo"),
|
||||
self.source.set_type,
|
||||
self.source.get_type,
|
||||
self.db.readonly,
|
||||
custom_values=self.get_custom_events())
|
||||
|
||||
self.date_check = MonitoredDate(
|
||||
self.top.get_object("eer_date_entry"),
|
||||
self.top.get_object("eer_date_stat"),
|
||||
self.source.get_date_object(),
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.readonly)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
Create the notebook tabs and inserts them into the main
|
||||
window.
|
||||
"""
|
||||
|
||||
notebook = self.top.get_object('notebook')
|
||||
notebook_ref = self.top.get_object('notebook_ref')
|
||||
|
||||
self._add_tab(notebook, self.primtab)
|
||||
self._add_tab(notebook_ref, self.reftab)
|
||||
self.track_ref_for_deletion("primtab")
|
||||
self.track_ref_for_deletion("reftab")
|
||||
|
||||
self.srcref_list = SourceEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.source)
|
||||
self._add_tab(notebook, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.attr_list = AttrEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.source.get_attribute_list())
|
||||
self._add_tab(notebook, self.attr_list)
|
||||
self.track_ref_for_deletion("attr_list")
|
||||
|
||||
self.note_tab = NoteTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.source.get_note_list(),
|
||||
notetype=gen.lib.NoteType.EVENT)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self.note_ref_tab = NoteTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.source_ref.get_note_list(),
|
||||
notetype=gen.lib.NoteType.EVENTREF)
|
||||
self._add_tab(notebook_ref, self.note_ref_tab)
|
||||
self.track_ref_for_deletion("note_ref_tab")
|
||||
|
||||
self.gallery_tab = GalleryTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.source.get_media_list())
|
||||
self._add_tab(notebook, self.gallery_tab)
|
||||
self.track_ref_for_deletion("gallery_tab")
|
||||
|
||||
self.backref_tab = EventBackRefList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.find_backlink_handles(self.source.handle),
|
||||
self.enable_warnbox)
|
||||
self._add_tab(notebook, self.backref_tab)
|
||||
self.track_ref_for_deletion("backref_tab")
|
||||
|
||||
self.attr_ref_list = AttrEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.source_ref.get_attribute_list())
|
||||
self._add_tab(notebook_ref, self.attr_ref_list)
|
||||
self.track_ref_for_deletion("attr_ref_list")
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
self._setup_notebook_tabs( notebook_ref)
|
||||
|
||||
def build_menu_names(self,eventref):
|
||||
if self.source:
|
||||
event_name = str(self.source.get_type())
|
||||
submenu_label = _('Event: %s') % event_name
|
||||
else:
|
||||
submenu_label = _('New Event')
|
||||
return (_('Event Reference Editor'),submenu_label)
|
||||
|
||||
def ok_clicked(self, obj):
|
||||
|
||||
trans = self.db.transaction_begin()
|
||||
if self.source.handle:
|
||||
self.commit_event(self.source,trans)
|
||||
self.db.transaction_commit(trans,_("Modify Event"))
|
||||
else:
|
||||
self.add_event(self.source,trans)
|
||||
self.db.transaction_commit(trans,_("Add Event"))
|
||||
self.source_ref.ref = self.source.handle
|
||||
|
||||
if self.update:
|
||||
self.update(self.source_ref,self.source)
|
||||
|
||||
self.close()
|
||||
|
||||
class EditFamilyEventRef(EditEventRef):
|
||||
|
||||
def __init__(self, state, uistate, track, event, event_ref, update):
|
||||
|
||||
EditEventRef.__init__(self, state, uistate, track, event,
|
||||
event_ref, update)
|
||||
|
||||
def _init_event(self):
|
||||
self.commit_event = self.db.commit_family_event
|
||||
self.add_event = self.db.add_family_event
|
||||
|
||||
def get_custom_events(self):
|
||||
return [ gen.lib.EventType((gen.lib.EventType.CUSTOM,val)) \
|
||||
for val in self.dbstate.db.get_family_event_types()]
|
||||
1138
src/gui/editors/editfamily.py
Normal file
1138
src/gui/editors/editfamily.py
Normal file
File diff suppressed because it is too large
Load Diff
423
src/gui/editors/editldsord.py
Normal file
423
src/gui/editors/editldsord.py
Normal file
@@ -0,0 +1,423 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
"""
|
||||
The EditLdsOrd module provides the EditLdsOrd class. This provides a
|
||||
mechanism for the user to edit personal LDS information.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gen.lib
|
||||
from BasicUtils import name_displayer
|
||||
import LdsUtils
|
||||
from glade import Glade
|
||||
from editsecondary import EditSecondary
|
||||
from objectentries import PlaceEntry
|
||||
from DisplayTabs import SourceEmbedList,NoteTab
|
||||
from gui.widgets import (PrivacyButton, MonitoredDate,
|
||||
MonitoredMenu, MonitoredStrMenu)
|
||||
from gui.selectors import SelectorFactory
|
||||
|
||||
_DATA_MAP = {
|
||||
gen.lib.LdsOrd.BAPTISM : [
|
||||
gen.lib.LdsOrd.STATUS_NONE,
|
||||
gen.lib.LdsOrd.STATUS_CHILD,
|
||||
gen.lib.LdsOrd.STATUS_CLEARED,
|
||||
gen.lib.LdsOrd.STATUS_COMPLETED,
|
||||
gen.lib.LdsOrd.STATUS_INFANT,
|
||||
gen.lib.LdsOrd.STATUS_PRE_1970,
|
||||
gen.lib.LdsOrd.STATUS_QUALIFIED,
|
||||
gen.lib.LdsOrd.STATUS_STILLBORN,
|
||||
gen.lib.LdsOrd.STATUS_SUBMITTED,
|
||||
gen.lib.LdsOrd.STATUS_UNCLEARED,
|
||||
],
|
||||
gen.lib.LdsOrd.CONFIRMATION : [
|
||||
gen.lib.LdsOrd.STATUS_NONE,
|
||||
gen.lib.LdsOrd.STATUS_CHILD,
|
||||
gen.lib.LdsOrd.STATUS_CLEARED,
|
||||
gen.lib.LdsOrd.STATUS_COMPLETED,
|
||||
gen.lib.LdsOrd.STATUS_INFANT,
|
||||
gen.lib.LdsOrd.STATUS_PRE_1970,
|
||||
gen.lib.LdsOrd.STATUS_QUALIFIED,
|
||||
gen.lib.LdsOrd.STATUS_STILLBORN,
|
||||
gen.lib.LdsOrd.STATUS_SUBMITTED,
|
||||
gen.lib.LdsOrd.STATUS_UNCLEARED,
|
||||
],
|
||||
gen.lib.LdsOrd.ENDOWMENT: [
|
||||
gen.lib.LdsOrd.STATUS_NONE,
|
||||
gen.lib.LdsOrd.STATUS_CHILD,
|
||||
gen.lib.LdsOrd.STATUS_CLEARED,
|
||||
gen.lib.LdsOrd.STATUS_COMPLETED,
|
||||
gen.lib.LdsOrd.STATUS_INFANT,
|
||||
gen.lib.LdsOrd.STATUS_PRE_1970,
|
||||
gen.lib.LdsOrd.STATUS_QUALIFIED,
|
||||
gen.lib.LdsOrd.STATUS_STILLBORN,
|
||||
gen.lib.LdsOrd.STATUS_SUBMITTED,
|
||||
gen.lib.LdsOrd.STATUS_UNCLEARED,
|
||||
],
|
||||
gen.lib.LdsOrd.SEAL_TO_PARENTS:[
|
||||
gen.lib.LdsOrd.STATUS_NONE,
|
||||
gen.lib.LdsOrd.STATUS_BIC,
|
||||
gen.lib.LdsOrd.STATUS_CLEARED,
|
||||
gen.lib.LdsOrd.STATUS_COMPLETED,
|
||||
gen.lib.LdsOrd.STATUS_DNS,
|
||||
gen.lib.LdsOrd.STATUS_PRE_1970,
|
||||
gen.lib.LdsOrd.STATUS_QUALIFIED,
|
||||
gen.lib.LdsOrd.STATUS_STILLBORN,
|
||||
gen.lib.LdsOrd.STATUS_SUBMITTED,
|
||||
gen.lib.LdsOrd.STATUS_UNCLEARED,
|
||||
],
|
||||
gen.lib.LdsOrd.SEAL_TO_SPOUSE :[
|
||||
gen.lib.LdsOrd.STATUS_NONE,
|
||||
gen.lib.LdsOrd.STATUS_CANCELED,
|
||||
gen.lib.LdsOrd.STATUS_CLEARED,
|
||||
gen.lib.LdsOrd.STATUS_COMPLETED,
|
||||
gen.lib.LdsOrd.STATUS_DNS,
|
||||
gen.lib.LdsOrd.STATUS_PRE_1970,
|
||||
gen.lib.LdsOrd.STATUS_QUALIFIED,
|
||||
gen.lib.LdsOrd.STATUS_DNS_CAN,
|
||||
gen.lib.LdsOrd.STATUS_SUBMITTED,
|
||||
gen.lib.LdsOrd.STATUS_UNCLEARED,
|
||||
],
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditLdsOrd class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditLdsOrd(EditSecondary):
|
||||
"""
|
||||
Displays a dialog that allows the user to edit an attribute.
|
||||
"""
|
||||
|
||||
def __init__(self, state, uistate, track, attrib, callback):
|
||||
"""
|
||||
Displays the dialog box.
|
||||
|
||||
parent - The class that called the Address editor.
|
||||
attrib - The attribute that is to be edited
|
||||
title - The title of the dialog box
|
||||
list - list of options for the pop down menu
|
||||
"""
|
||||
EditSecondary.__init__(self, state, uistate, track, attrib, callback)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.lds-width'
|
||||
self.height_key = 'interface.lds-height'
|
||||
|
||||
self.top = Glade()
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object('title'),
|
||||
_('LDS Ordinance Editor'))
|
||||
self.share_btn = self.top.get_object('share_place')
|
||||
self.add_del_btn = self.top.get_object('add_del_place')
|
||||
|
||||
def _connect_signals(self):
|
||||
self.parents_select.connect('clicked',self.select_parents_clicked)
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
self.define_help_button(self.top.get_object('help'))
|
||||
self.define_ok_button(self.top.get_object('ok'),self.save)
|
||||
|
||||
def _get_types(self):
|
||||
return (gen.lib.LdsOrd.BAPTISM,
|
||||
gen.lib.LdsOrd.ENDOWMENT,
|
||||
gen.lib.LdsOrd.CONFIRMATION,
|
||||
gen.lib.LdsOrd.SEAL_TO_PARENTS)
|
||||
|
||||
def _setup_fields(self):
|
||||
|
||||
self.parents_label = self.top.get_object('parents_label')
|
||||
self.parents = self.top.get_object('parents')
|
||||
self.parents_select = self.top.get_object('parents_select')
|
||||
|
||||
self.priv = PrivacyButton(
|
||||
self.top.get_object("private"),
|
||||
self.obj, self.db.readonly)
|
||||
|
||||
self.date_field = MonitoredDate(
|
||||
self.top.get_object("date_entry"),
|
||||
self.top.get_object("date_stat"),
|
||||
self.obj.get_date_object(),
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.readonly)
|
||||
|
||||
self.place_field = PlaceEntry(
|
||||
self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.top.get_object("place"),
|
||||
self.obj.set_place_handle,
|
||||
self.obj.get_place_handle,
|
||||
self.add_del_btn,
|
||||
self.share_btn)
|
||||
|
||||
self.type_menu = MonitoredMenu(
|
||||
self.top.get_object('type'),
|
||||
self.obj.set_type,
|
||||
self.obj.get_type,
|
||||
[(item[1],item[0]) for item in gen.lib.LdsOrd._TYPE_MAP
|
||||
if item[0] in self._get_types()],
|
||||
self.db.readonly,
|
||||
changed=self.ord_type_changed)
|
||||
|
||||
self.temple_menu = MonitoredStrMenu(
|
||||
self.top.get_object('temple'),
|
||||
self.obj.set_temple,
|
||||
self.obj.get_temple,
|
||||
LdsUtils.TEMPLES.name_code_data(),
|
||||
self.db.readonly)
|
||||
|
||||
self.status_menu = MonitoredMenu(
|
||||
self.top.get_object('status'),
|
||||
self.obj.set_status,
|
||||
self.obj.get_status,
|
||||
[(item[1],item[0]) for item in gen.lib.LdsOrd._STATUS_MAP
|
||||
if item[0] in _DATA_MAP[self.obj.get_type()] ],
|
||||
self.db.readonly)
|
||||
|
||||
self.ord_type_changed()
|
||||
self.update_parent_label()
|
||||
|
||||
def ord_type_changed(self):
|
||||
if self.obj.get_type() == gen.lib.LdsOrd.BAPTISM:
|
||||
self.parents.hide()
|
||||
self.parents_label.hide()
|
||||
self.parents_select.hide()
|
||||
elif self.obj.get_type() == gen.lib.LdsOrd.ENDOWMENT:
|
||||
self.parents.hide()
|
||||
self.parents_label.hide()
|
||||
self.parents_select.hide()
|
||||
elif self.obj.get_type() == gen.lib.LdsOrd.SEAL_TO_PARENTS:
|
||||
self.parents.show()
|
||||
self.parents_label.show()
|
||||
self.parents_select.show()
|
||||
new_data = [(item[1],item[0]) for item in gen.lib.LdsOrd._STATUS_MAP
|
||||
if item[0] in _DATA_MAP[self.obj.get_type()] ]
|
||||
self.status_menu.change_menu(new_data)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
notebook = gtk.Notebook()
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate, self.track,self.obj))
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=gen.lib.NoteType.LDS))
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
notebook.show_all()
|
||||
self.top.get_object('vbox').pack_start(notebook,True)
|
||||
|
||||
def select_parents_clicked(self, obj):
|
||||
SelectFamily = SelectorFactory('Family')
|
||||
|
||||
dialog = SelectFamily(self.dbstate,self.uistate,self.track)
|
||||
family = dialog.run()
|
||||
if family:
|
||||
self.obj.set_family_handle(family.handle)
|
||||
self.update_parent_label()
|
||||
|
||||
def update_parent_label(self):
|
||||
handle = self.obj.get_family_handle()
|
||||
if handle:
|
||||
family = self.dbstate.db.get_family_from_handle(handle)
|
||||
f = self.dbstate.db.get_person_from_handle(
|
||||
family.get_father_handle())
|
||||
m = self.dbstate.db.get_person_from_handle(
|
||||
family.get_mother_handle())
|
||||
if f and m:
|
||||
label = _("%(father)s and %(mother)s [%(gramps_id)s]") % {
|
||||
'father' : name_displayer.display(f),
|
||||
'mother' : name_displayer.display(m),
|
||||
'gramps_id' : family.gramps_id,
|
||||
}
|
||||
elif f:
|
||||
label = _("%(father)s [%(gramps_id)s]") % {
|
||||
'father' : name_displayer.display(f),
|
||||
'gramps_id' : family.gramps_id,
|
||||
}
|
||||
elif m:
|
||||
label = _("%(mother)s [%(gramps_id)s]") % {
|
||||
'mother' : name_displayer.display(m),
|
||||
'gramps_id' : family.gramps_id,
|
||||
}
|
||||
else:
|
||||
# No translation for bare gramps_id
|
||||
label = "[%(gramps_id)s]" % {
|
||||
'gramps_id' : family.gramps_id,
|
||||
}
|
||||
else:
|
||||
label = ""
|
||||
|
||||
self.parents.set_text(label)
|
||||
|
||||
def build_menu_names(self, attrib):
|
||||
label = _("LDS Ordinance")
|
||||
return (label, _('LDS Ordinance Editor'))
|
||||
|
||||
def save(self,*obj):
|
||||
"""
|
||||
Called when the OK button is pressed. Gets data from the
|
||||
form and updates the LdsOrd data structure.
|
||||
"""
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditFamilyLdsOrd
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditFamilyLdsOrd(EditSecondary):
|
||||
"""
|
||||
Displays a dialog that allows the user to edit an attribute.
|
||||
"""
|
||||
|
||||
def __init__(self, state, uistate, track, attrib, callback):
|
||||
"""
|
||||
Displays the dialog box.
|
||||
|
||||
parent - The class that called the Address editor.
|
||||
attrib - The attribute that is to be edited
|
||||
title - The title of the dialog box
|
||||
list - list of options for the pop down menu
|
||||
"""
|
||||
EditSecondary.__init__(self, state, uistate, track, attrib, callback)
|
||||
|
||||
def _local_init(self):
|
||||
self.top = Glade()
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object('title'),
|
||||
_('LDS Ordinance Editor'))
|
||||
self.share_btn = self.top.get_object('share_place')
|
||||
self.add_del_btn = self.top.get_object('add_del_place')
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
self.define_help_button(self.top.get_object('help'))
|
||||
self.define_ok_button(self.top.get_object('ok'),self.save)
|
||||
|
||||
def _get_types(self):
|
||||
return (gen.lib.LdsOrd.SEAL_TO_SPOUSE,)
|
||||
|
||||
def _setup_fields(self):
|
||||
|
||||
self.parents_label = self.top.get_object('parents_label')
|
||||
self.parents = self.top.get_object('parents')
|
||||
self.parents_select = self.top.get_object('parents_select')
|
||||
|
||||
self.priv = PrivacyButton(
|
||||
self.top.get_object("private"),
|
||||
self.obj, self.db.readonly)
|
||||
|
||||
self.date_field = MonitoredDate(
|
||||
self.top.get_object("date_entry"),
|
||||
self.top.get_object("date_stat"),
|
||||
self.obj.get_date_object(),
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.readonly)
|
||||
|
||||
self.place_field = PlaceEntry(
|
||||
self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.top.get_object("place"),
|
||||
self.obj.set_place_handle,
|
||||
self.obj.get_place_handle,
|
||||
self.add_del_btn,
|
||||
self.share_btn)
|
||||
|
||||
self.type_menu = MonitoredMenu(
|
||||
self.top.get_object('type'),
|
||||
self.obj.set_type,
|
||||
self.obj.get_type,
|
||||
[(item[1],item[0]) for item in gen.lib.LdsOrd._TYPE_MAP
|
||||
if item[0] in self._get_types()],
|
||||
self.db.readonly)
|
||||
|
||||
self.temple_menu = MonitoredStrMenu(
|
||||
self.top.get_object('temple'),
|
||||
self.obj.set_temple,
|
||||
self.obj.get_temple,
|
||||
LdsUtils.TEMPLES.name_code_data(),
|
||||
self.db.readonly)
|
||||
|
||||
self.status_menu = MonitoredMenu(
|
||||
self.top.get_object('status'),
|
||||
self.obj.set_status,
|
||||
self.obj.get_status,
|
||||
[(item[1],item[0]) for item in gen.lib.LdsOrd._STATUS_MAP
|
||||
if item[0] in _DATA_MAP[self.obj.get_type()]],
|
||||
self.db.readonly)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
notebook = gtk.Notebook()
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate, self.track,self.obj))
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=gen.lib.NoteType.LDS))
|
||||
|
||||
notebook.show_all()
|
||||
self.top.get_object('vbox').pack_start(notebook,True)
|
||||
|
||||
def build_menu_names(self, attrib):
|
||||
label = _("LDS Ordinance")
|
||||
return (label, _('LDS Ordinance Editor'))
|
||||
|
||||
def save(self,*obj):
|
||||
"""
|
||||
Called when the OK button is pressed. Gets data from the
|
||||
form and updates the LdsOrd data structure.
|
||||
"""
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
111
src/gui/editors/editlocation.py
Normal file
111
src/gui/editors/editlocation.py
Normal file
@@ -0,0 +1,111 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from editsecondary import EditSecondary
|
||||
from glade import Glade
|
||||
from gui.widgets import MonitoredEntry
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# LocationEditor class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditLocation(EditSecondary):
|
||||
|
||||
def __init__(self,dbstate,uistate,track,location,callback):
|
||||
EditSecondary.__init__(self, dbstate, uistate, track,
|
||||
location, callback)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.location-width'
|
||||
self.height_key = 'interface.location-height'
|
||||
self.top = Glade()
|
||||
self.set_window(self.top.toplevel, None,
|
||||
_('Location Editor'))
|
||||
|
||||
def _setup_fields(self):
|
||||
self.street = MonitoredEntry(
|
||||
self.top.get_object("street"),
|
||||
self.obj.set_street,
|
||||
self.obj.get_street,
|
||||
self.db.readonly)
|
||||
|
||||
self.city = MonitoredEntry(
|
||||
self.top.get_object("city"),
|
||||
self.obj.set_city,
|
||||
self.obj.get_city,
|
||||
self.db.readonly)
|
||||
|
||||
self.state = MonitoredEntry(
|
||||
self.top.get_object("state"),
|
||||
self.obj.set_state,
|
||||
self.obj.get_state,
|
||||
self.db.readonly)
|
||||
|
||||
self.postal = MonitoredEntry(
|
||||
self.top.get_object("postal"),
|
||||
self.obj.set_postal_code,
|
||||
self.obj.get_postal_code,
|
||||
self.db.readonly)
|
||||
|
||||
self.phone = MonitoredEntry(
|
||||
self.top.get_object("phone"),
|
||||
self.obj.set_phone,
|
||||
self.obj.get_phone,
|
||||
self.db.readonly)
|
||||
|
||||
self.parish = MonitoredEntry(
|
||||
self.top.get_object("parish"),
|
||||
self.obj.set_parish,
|
||||
self.obj.get_parish,
|
||||
self.db.readonly)
|
||||
|
||||
self.county = MonitoredEntry(
|
||||
self.top.get_object("county"),
|
||||
self.obj.set_county,
|
||||
self.obj.get_county,
|
||||
self.db.readonly)
|
||||
|
||||
self.country = MonitoredEntry(
|
||||
self.top.get_object("country"),
|
||||
self.obj.set_country,
|
||||
self.obj.get_country,
|
||||
self.db.readonly)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_cancel_button(self.top.get_object('button119'))
|
||||
self.define_ok_button(self.top.get_object('button118'),self.save)
|
||||
self.define_help_button(self.top.get_object('button128'))
|
||||
|
||||
def save(self,*obj):
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
|
||||
|
||||
374
src/gui/editors/editmedia.py
Normal file
374
src/gui/editors/editmedia.py
Normal file
@@ -0,0 +1,374 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# Copyright (C) 2009 Gary Burton
|
||||
#
|
||||
# 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 _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gui.utils import open_file_with_default_application
|
||||
import gen.lib
|
||||
import Mime
|
||||
import ThumbNails
|
||||
import Utils
|
||||
from editprimary import EditPrimary
|
||||
from gui.widgets import MonitoredDate, MonitoredEntry, PrivacyButton
|
||||
from DisplayTabs import (SourceEmbedList, AttrEmbedList, NoteTab,
|
||||
MediaBackRefList)
|
||||
from addmedia import AddMediaObject
|
||||
from QuestionDialog import ErrorDialog
|
||||
from glade import Glade
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditMedia
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditMedia(EditPrimary):
|
||||
|
||||
def __init__(self, dbstate, uistate, track, obj, callback=None):
|
||||
|
||||
EditPrimary.__init__(self, dbstate, uistate, track, obj,
|
||||
dbstate.db.get_object_from_handle,
|
||||
dbstate.db.get_object_from_gramps_id, callback)
|
||||
if not self.obj.get_handle():
|
||||
#show the addmedia dialog immediately, with track of parent.
|
||||
AddMediaObject(dbstate, self.uistate, self.track, self.obj,
|
||||
self._update_addmedia)
|
||||
|
||||
def empty_object(self):
|
||||
return gen.lib.MediaObject()
|
||||
|
||||
def get_menu_title(self):
|
||||
if self.obj.get_handle():
|
||||
name = self.obj.get_description()
|
||||
if not name:
|
||||
name = self.obj.get_path()
|
||||
if not name:
|
||||
name = self.obj.get_mime_type()
|
||||
if not name:
|
||||
name = _('Note')
|
||||
dialog_title = _('Media: %s') % name
|
||||
else:
|
||||
dialog_title = _('New Media')
|
||||
return dialog_title
|
||||
|
||||
def _local_init(self):
|
||||
assert(self.obj)
|
||||
self.width_key = 'interface.media-width'
|
||||
self.height_key = 'interface.media-height'
|
||||
|
||||
self.glade = Glade()
|
||||
self.set_window(self.glade.toplevel,
|
||||
None, self.get_menu_title())
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_cancel_button(self.glade.get_object('button91'))
|
||||
self.define_ok_button(self.glade.get_object('ok'), self.save)
|
||||
self.define_help_button(self.glade.get_object('button102'))
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('media-rebuild', self._do_close)
|
||||
self._add_db_signal('media-delete', self.check_for_close)
|
||||
|
||||
def _setup_fields(self):
|
||||
self.date_field = MonitoredDate(self.glade.get_object("date_entry"),
|
||||
self.glade.get_object("date_edit"),
|
||||
self.obj.get_date_object(),
|
||||
self.uistate, self.track,
|
||||
self.db.readonly)
|
||||
|
||||
self.descr_window = MonitoredEntry(self.glade.get_object("description"),
|
||||
self.obj.set_description,
|
||||
self.obj.get_description,
|
||||
self.db.readonly)
|
||||
|
||||
self.gid = MonitoredEntry(self.glade.get_object("gid"),
|
||||
self.obj.set_gramps_id,
|
||||
self.obj.get_gramps_id, self.db.readonly)
|
||||
|
||||
self.privacy = PrivacyButton(self.glade.get_object("private"),
|
||||
self.obj, self.db.readonly)
|
||||
|
||||
self.pixmap = self.glade.get_object("pixmap")
|
||||
ebox = self.glade.get_object('eventbox')
|
||||
ebox.connect('button-press-event', self.button_press_event)
|
||||
|
||||
self.mimetext = self.glade.get_object("type")
|
||||
self.setup_filepath()
|
||||
self.determine_mime()
|
||||
self.draw_preview()
|
||||
|
||||
def determine_mime(self):
|
||||
descr = Mime.get_description(self.obj.get_mime_type())
|
||||
if descr:
|
||||
self.mimetext.set_text(descr)
|
||||
|
||||
path = self.file_path.get_text()
|
||||
path_full = Utils.media_path_full(self.db, path)
|
||||
if path != self.obj.get_path() and path_full != self.obj.get_path():
|
||||
#redetermine mime
|
||||
mime = Mime.get_type(Utils.find_file(path_full))
|
||||
self.obj.set_mime_type(mime)
|
||||
descr = Mime.get_description(mime)
|
||||
if descr:
|
||||
self.mimetext.set_text(descr)
|
||||
else:
|
||||
self.mimetext.set_text(_('Unknown'))
|
||||
#if mime type not set, is note
|
||||
if not self.obj.get_mime_type():
|
||||
self.mimetext.set_text(_('Note'))
|
||||
|
||||
def draw_preview(self):
|
||||
mtype = self.obj.get_mime_type()
|
||||
if mtype:
|
||||
pb = ThumbNails.get_thumbnail_image(
|
||||
Utils.media_path_full(self.db, self.obj.get_path()),
|
||||
mtype)
|
||||
self.pixmap.set_from_pixbuf(pb)
|
||||
else:
|
||||
pb = Mime.find_mime_type_pixbuf('text/plain')
|
||||
self.pixmap.set_from_pixbuf(pb)
|
||||
|
||||
def setup_filepath(self):
|
||||
self.select = self.glade.get_object('file_select')
|
||||
self.file_path = self.glade.get_object("path")
|
||||
|
||||
fname = self.obj.get_path()
|
||||
self.file_path.set_text(fname)
|
||||
self.select.connect('clicked', self.select_file)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
notebook = gtk.Notebook()
|
||||
|
||||
self.src_tab = SourceEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj)
|
||||
self._add_tab(notebook, self.src_tab)
|
||||
self.track_ref_for_deletion("src_tab")
|
||||
|
||||
self.attr_tab = AttrEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_attribute_list())
|
||||
self._add_tab(notebook, self.attr_tab)
|
||||
self.track_ref_for_deletion("attr_tab")
|
||||
|
||||
self.note_tab = NoteTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=gen.lib.NoteType.MEDIA)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self.backref_tab = MediaBackRefList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.find_backlink_handles(self.obj.handle))
|
||||
self.backref_list = self._add_tab(notebook, self.backref_tab)
|
||||
self.track_ref_for_deletion("backref_tab")
|
||||
self.track_ref_for_deletion("backref_list")
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
notebook.show_all()
|
||||
self.glade.get_object('vbox').pack_start(notebook, True)
|
||||
|
||||
def build_menu_names(self, person):
|
||||
return (_('Edit Media Object'), self.get_menu_title())
|
||||
|
||||
def button_press_event(self, obj, event):
|
||||
if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
|
||||
self.view_media(obj)
|
||||
|
||||
def view_media(self, obj):
|
||||
ref_obj = self.dbstate.db.get_object_from_handle(self.obj.handle)
|
||||
|
||||
if ref_obj:
|
||||
media_path = Utils.media_path_full(self.dbstate.db,
|
||||
ref_obj.get_path())
|
||||
open_file_with_default_application(media_path)
|
||||
|
||||
def select_file(self, val):
|
||||
self.determine_mime()
|
||||
path = self.file_path.get_text()
|
||||
self.obj.set_path(Utils.get_unicode_path(path))
|
||||
AddMediaObject(self.dbstate, self.uistate, self.track, self.obj,
|
||||
self._update_addmedia)
|
||||
|
||||
def _update_addmedia(self, obj):
|
||||
"""
|
||||
Called when the add media dialog has been called.
|
||||
This allows us to update the main form in response to
|
||||
any changes: Redraw relevant fields: description, mimetype and path
|
||||
"""
|
||||
for obj in (self.descr_window, ):
|
||||
obj.update()
|
||||
fname = self.obj.get_path()
|
||||
self.file_path.set_text(fname)
|
||||
self.determine_mime()
|
||||
self.draw_preview()
|
||||
|
||||
def save(self, *obj):
|
||||
self.ok_button.set_sensitive(False)
|
||||
|
||||
if self.object_is_empty():
|
||||
ErrorDialog(_("Cannot save media object"),
|
||||
_("No data exists for this media object. Please "
|
||||
"enter data or cancel the edit."))
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
(uses_dupe_id, id) = self._uses_duplicate_id()
|
||||
if uses_dupe_id:
|
||||
prim_object = self.get_from_gramps_id(id)
|
||||
name = prim_object.get_description()
|
||||
msg1 = _("Cannot save media object. ID already exists.")
|
||||
msg2 = _("You have attempted to use the existing Gramps ID with "
|
||||
"value %(id)s. This value is already used by '"
|
||||
"%(prim_object)s'. Please enter a different ID or leave "
|
||||
"blank to get the next available ID value.") % {
|
||||
'id' : id, 'prim_object' : name }
|
||||
ErrorDialog(msg1, msg2)
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
path = self.file_path.get_text()
|
||||
self.determine_mime()
|
||||
|
||||
self.obj.set_path(Utils.get_unicode_path(path))
|
||||
|
||||
trans = self.db.transaction_begin()
|
||||
if not self.obj.get_handle():
|
||||
self.db.add_object(self.obj, trans)
|
||||
msg = _("Add Media Object (%s)") % self.obj.get_description()
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_object_gramps_id())
|
||||
self.db.commit_media_object(self.obj, trans)
|
||||
msg = _("Edit Media Object (%s)") % self.obj.get_description()
|
||||
|
||||
self.db.transaction_commit(trans, msg)
|
||||
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
self.backref_list.close()
|
||||
|
||||
def data_has_changed(self):
|
||||
"""
|
||||
A date comparison can fail incorrectly because we have made the
|
||||
decision to store entered text in the date. However, there is no
|
||||
entered date when importing from a XML file, so we can get an
|
||||
incorrect fail.
|
||||
"""
|
||||
|
||||
if self.db.readonly:
|
||||
return False
|
||||
elif self.obj.handle:
|
||||
orig = self.get_from_handle(self.obj.handle)
|
||||
if orig:
|
||||
cmp_obj = orig
|
||||
else:
|
||||
cmp_obj = self.empty_object()
|
||||
return cmp(cmp_obj.serialize(True)[1:],
|
||||
self.obj.serialize(True)[1:]) != 0
|
||||
else:
|
||||
cmp_obj = self.empty_object()
|
||||
return cmp(cmp_obj.serialize(True)[1:],
|
||||
self.obj.serialize()[1:]) != 0
|
||||
|
||||
class DeleteMediaQuery(object):
|
||||
|
||||
def __init__(self, dbstate, uistate, media_handle, the_lists):
|
||||
self.db = dbstate.db
|
||||
self.uistate = uistate
|
||||
self.media_handle = media_handle
|
||||
self.the_lists = the_lists
|
||||
|
||||
def query_response(self):
|
||||
trans = self.db.transaction_begin()
|
||||
self.db.disable_signals()
|
||||
|
||||
(person_list, family_list, event_list,
|
||||
place_list,source_list) = self.the_lists
|
||||
|
||||
for handle in person_list:
|
||||
person = self.db.get_person_from_handle(handle)
|
||||
new_list = [ photo for photo in person.get_media_list() \
|
||||
if photo.get_reference_handle() != self.media_handle ]
|
||||
person.set_media_list(new_list)
|
||||
self.db.commit_person(person, trans)
|
||||
|
||||
for handle in family_list:
|
||||
family = self.db.get_family_from_handle(handle)
|
||||
new_list = [ photo for photo in family.get_media_list() \
|
||||
if photo.get_reference_handle() != self.media_handle ]
|
||||
family.set_media_list(new_list)
|
||||
self.db.commit_family(family, trans)
|
||||
|
||||
for handle in event_list:
|
||||
event = self.db.get_event_from_handle(handle)
|
||||
new_list = [ photo for photo in event.get_media_list() \
|
||||
if photo.get_reference_handle() != self.media_handle ]
|
||||
event.set_media_list(new_list)
|
||||
self.db.commit_event(event, trans)
|
||||
|
||||
for handle in place_list:
|
||||
place = self.db.get_place_from_handle(handle)
|
||||
new_list = [ photo for photo in place.get_media_list() \
|
||||
if photo.get_reference_handle() != self.media_handle ]
|
||||
place.set_media_list(new_list)
|
||||
self.db.commit_place(place, trans)
|
||||
|
||||
for handle in source_list:
|
||||
source = self.db.get_source_from_handle(handle)
|
||||
new_list = [ photo for photo in source.get_media_list() \
|
||||
if photo.get_reference_handle() != self.media_handle ]
|
||||
source.set_media_list(new_list)
|
||||
self.db.commit_source(source, trans)
|
||||
|
||||
self.db.enable_signals()
|
||||
self.db.remove_object(self.media_handle, trans)
|
||||
self.db.transaction_commit(trans, _("Remove Media Object"))
|
||||
573
src/gui/editors/editmediaref.py
Normal file
573
src/gui/editors/editmediaref.py
Normal file
@@ -0,0 +1,573 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2008-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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 TransUtils import sgettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gui.utils import open_file_with_default_application
|
||||
import const
|
||||
import Mime
|
||||
import ThumbNails
|
||||
import Utils
|
||||
from gen.lib import NoteType
|
||||
from glade import Glade
|
||||
from DisplayTabs import (SourceEmbedList, AttrEmbedList, MediaBackRefList,
|
||||
NoteTab)
|
||||
from gui.widgets import MonitoredSpinButton, MonitoredEntry, PrivacyButton
|
||||
from editreference import RefTab, EditReference
|
||||
from addmedia import AddMediaObject
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditMediaRef
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditMediaRef(EditReference):
|
||||
|
||||
def __init__(self, state, uistate, track, media, media_ref, update):
|
||||
EditReference.__init__(self, state, uistate, track, media,
|
||||
media_ref, update)
|
||||
if not self.source.get_handle():
|
||||
#show the addmedia dialog immediately, with track of parent.
|
||||
AddMediaObject(state, self.uistate, self.track, self.source,
|
||||
self._update_addmedia)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.media-ref-width'
|
||||
self.height_key = 'interface.media-ref-height'
|
||||
self.top = Glade()
|
||||
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object('title'),
|
||||
_('Media Reference Editor'))
|
||||
self.define_warn_box(self.top.get_object("warn_box"))
|
||||
self.top.get_object("label427").set_text(_("Y coordinate|Y"))
|
||||
self.top.get_object("label428").set_text(_("Y coordinate|Y"))
|
||||
|
||||
tblref = self.top.get_object('table50')
|
||||
notebook = self.top.get_object('notebook_ref')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.reftab = RefTab(self.dbstate, self.uistate, self.track,
|
||||
_('General'), tblref)
|
||||
tblref = self.top.get_object('table2')
|
||||
notebook = self.top.get_object('notebook_shared')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.primtab = RefTab(self.dbstate, self.uistate, self.track,
|
||||
_('_General'), tblref)
|
||||
|
||||
def draw_preview(self):
|
||||
"""
|
||||
Draw the two preview images. This method can be called on eg change of
|
||||
the path.
|
||||
"""
|
||||
self.mtype = self.source.get_mime_type()
|
||||
fullpath = Utils.media_path_full(self.db, self.source.get_path())
|
||||
self.pix = ThumbNails.get_thumbnail_image(fullpath,
|
||||
self.mtype)
|
||||
self.pixmap.set_from_pixbuf(self.pix)
|
||||
|
||||
self.subpix = ThumbNails.get_thumbnail_image(fullpath,
|
||||
self.mtype,
|
||||
self.rectangle)
|
||||
self.subpixmap.set_from_pixbuf(self.subpix)
|
||||
|
||||
mt = Mime.get_description(self.mtype)
|
||||
self.top.get_object("type").set_text(mt if mt else "")
|
||||
|
||||
def _setup_fields(self):
|
||||
ebox_shared = self.top.get_object('eventbox')
|
||||
ebox_shared.connect('button-press-event', self.button_press_event)
|
||||
|
||||
if not self.dbstate.db.readonly:
|
||||
self.button_press_coords = (0, 0)
|
||||
ebox_ref = self.top.get_object('eventbox1')
|
||||
ebox_ref.connect('button-press-event', self.button_press_event_ref)
|
||||
ebox_ref.connect('button-release-event',
|
||||
self.button_release_event_ref)
|
||||
ebox_ref.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
||||
ebox_ref.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
|
||||
|
||||
self.pixmap = self.top.get_object("pixmap")
|
||||
|
||||
coord = self.source_ref.get_rectangle()
|
||||
#upgrade path: set invalid (from eg old db) to none
|
||||
|
||||
if coord is not None and coord in (
|
||||
(None,)*4,
|
||||
(0, 0, 100, 100),
|
||||
(coord[0], coord[1])*2
|
||||
):
|
||||
coord = None
|
||||
|
||||
self.rectangle = coord
|
||||
self.subpixmap = self.top.get_object("subpixmap")
|
||||
|
||||
self.draw_preview()
|
||||
|
||||
corners = ["corner1_x", "corner1_y", "corner2_x", "corner2_y"]
|
||||
|
||||
if coord and isinstance(coord, tuple):
|
||||
for index, corner in enumerate(corners):
|
||||
self.top.get_object(corner).set_value(coord[index])
|
||||
else:
|
||||
for corner, value in zip(corners, [0, 0, 100, 100]):
|
||||
self.top.get_object(corner).set_value(value)
|
||||
|
||||
if self.dbstate.db.readonly:
|
||||
for corner in corners:
|
||||
self.top.get_object(corner).set_sensitive(False)
|
||||
|
||||
self.corner1_x_spinbutton = MonitoredSpinButton(
|
||||
self.top.get_object("corner1_x"),
|
||||
self.set_corner1_x,
|
||||
self.get_corner1_x,
|
||||
self.db.readonly)
|
||||
|
||||
self.corner1_y_spinbutton = MonitoredSpinButton(
|
||||
self.top.get_object("corner1_y"),
|
||||
self.set_corner1_y,
|
||||
self.get_corner1_y,
|
||||
self.db.readonly)
|
||||
|
||||
self.corner2_x_spinbutton = MonitoredSpinButton(
|
||||
self.top.get_object("corner2_x"),
|
||||
self.set_corner2_x,
|
||||
self.get_corner2_x,
|
||||
self.db.readonly)
|
||||
|
||||
self.corner2_y_spinbutton = MonitoredSpinButton(
|
||||
self.top.get_object("corner2_y"),
|
||||
self.set_corner2_y,
|
||||
self.get_corner2_y,
|
||||
self.db.readonly)
|
||||
|
||||
self.descr_window = MonitoredEntry(
|
||||
self.top.get_object("description"),
|
||||
self.source.set_description,
|
||||
self.source.get_description,
|
||||
self.db.readonly)
|
||||
|
||||
self.ref_privacy = PrivacyButton(
|
||||
self.top.get_object("private"),
|
||||
self.source_ref,
|
||||
self.db.readonly)
|
||||
|
||||
self.gid = MonitoredEntry(
|
||||
self.top.get_object("gid"),
|
||||
self.source.set_gramps_id,
|
||||
self.source.get_gramps_id,
|
||||
self.db.readonly)
|
||||
|
||||
self.privacy = PrivacyButton(
|
||||
self.top.get_object("privacy"),
|
||||
self.source,
|
||||
self.db.readonly)
|
||||
|
||||
self.path_obj = MonitoredEntry(
|
||||
self.top.get_object("path"),
|
||||
self.source.set_path,
|
||||
self.source.get_path,
|
||||
self.db.readonly)
|
||||
|
||||
def set_corner1_x(self, value):
|
||||
"""
|
||||
Callback for the signal handling of the spinbutton for the first
|
||||
corner x coordinate of the subsection.
|
||||
Updates the subsection thumbnail using the given value
|
||||
|
||||
@param value: the first corner x coordinate of the subsection in int
|
||||
"""
|
||||
|
||||
if self.rectangle is None:
|
||||
self.rectangle = (0,0,100,100)
|
||||
self.rectangle = (value,) + self.rectangle[1:]
|
||||
self.update_subpixmap()
|
||||
|
||||
def set_corner1_y(self, value):
|
||||
"""
|
||||
Callback for the signal handling of the spinbutton for the first
|
||||
corner y coordinate of the subsection.
|
||||
Updates the subsection thumbnail using the given value
|
||||
|
||||
@param value: the first corner y coordinate of the subsection in int
|
||||
"""
|
||||
|
||||
if self.rectangle is None:
|
||||
self.rectangle = (0,0,100,100)
|
||||
self.rectangle = self.rectangle[:1] + (value,) + self.rectangle[2:]
|
||||
self.update_subpixmap()
|
||||
|
||||
def set_corner2_x(self, value):
|
||||
"""
|
||||
Callback for the signal handling of the spinbutton for the second
|
||||
corner x coordinate of the subsection.
|
||||
Updates the subsection thumbnail using the given value
|
||||
|
||||
@param value: the second corner x coordinate of the subsection in int
|
||||
"""
|
||||
|
||||
if self.rectangle is None:
|
||||
self.rectangle = (0,0,100,100)
|
||||
self.rectangle = self.rectangle[:2] + (value,) + self.rectangle[3:]
|
||||
self.update_subpixmap()
|
||||
|
||||
def set_corner2_y(self, value):
|
||||
"""
|
||||
Callback for the signal handling of the spinbutton for the second
|
||||
corner y coordinate of the subsection.
|
||||
Updates the subsection thumbnail using the given value
|
||||
|
||||
@param value: the second corner y coordinate of the subsection in int
|
||||
"""
|
||||
|
||||
if self.rectangle is None:
|
||||
self.rectangle = (0,0,100,100)
|
||||
self.rectangle = self.rectangle[:3] + (value,)
|
||||
self.update_subpixmap()
|
||||
|
||||
def get_corner1_x(self):
|
||||
"""
|
||||
Callback for the signal handling of the spinbutton for the first corner
|
||||
x coordinate of the subsection.
|
||||
|
||||
@returns: the first corner x coordinate of the subsection or 0 if
|
||||
there is no selection
|
||||
"""
|
||||
|
||||
if self.rectangle is not None:
|
||||
return self.rectangle[0]
|
||||
else:
|
||||
return 0
|
||||
|
||||
def get_corner1_y(self):
|
||||
"""
|
||||
Callback for the signal handling of the spinbutton for the first corner
|
||||
y coordinate of the subsection.
|
||||
|
||||
@returns: the first corner y coordinate of the subsection or 0 if
|
||||
there is no selection
|
||||
"""
|
||||
|
||||
if self.rectangle is not None:
|
||||
return self.rectangle[1]
|
||||
else:
|
||||
return 0
|
||||
|
||||
def get_corner2_x(self):
|
||||
"""
|
||||
Callback for the signal handling of the spinbutton for the second
|
||||
corner x coordinate of the subsection.
|
||||
|
||||
@returns: the second corner x coordinate of the subsection or 100 if
|
||||
there is no selection
|
||||
"""
|
||||
|
||||
if self.rectangle is not None:
|
||||
return self.rectangle[2]
|
||||
else:
|
||||
return 100
|
||||
|
||||
def get_corner2_y(self):
|
||||
"""
|
||||
Callback for the signal handling of the spinbutton for the second
|
||||
corner x coordinate of the subsection.
|
||||
|
||||
@returns: the second corner x coordinate of the subsection or 100 if
|
||||
there is no selection
|
||||
"""
|
||||
|
||||
if self.rectangle is not None:
|
||||
return self.rectangle[3]
|
||||
else:
|
||||
return 100
|
||||
|
||||
def update_subpixmap(self):
|
||||
"""
|
||||
Updates the thumbnail of the specified subsection
|
||||
"""
|
||||
|
||||
path = self.source.get_path()
|
||||
if path is None:
|
||||
self.subpixmap.hide()
|
||||
else:
|
||||
try:
|
||||
fullpath = Utils.media_path_full(self.db, path)
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_file(fullpath)
|
||||
width = pixbuf.get_width()
|
||||
height = pixbuf.get_height()
|
||||
upper_x = min(self.rectangle[0], self.rectangle[2])/100.
|
||||
lower_x = max(self.rectangle[0], self.rectangle[2])/100.
|
||||
upper_y = min(self.rectangle[1], self.rectangle[3])/100.
|
||||
lower_y = max(self.rectangle[1], self.rectangle[3])/100.
|
||||
sub_x = int(upper_x * width)
|
||||
sub_y = int(upper_y * height)
|
||||
sub_width = int((lower_x - upper_x) * width)
|
||||
sub_height = int((lower_y - upper_y) * height)
|
||||
if sub_width > 0 and sub_height > 0:
|
||||
pixbuf = pixbuf.subpixbuf(sub_x, sub_y, sub_width, sub_height)
|
||||
width = sub_width
|
||||
height = sub_height
|
||||
ratio = float(max(height, width))
|
||||
scale = const.THUMBSCALE / ratio
|
||||
x = int(scale * width)
|
||||
y = int(scale * height)
|
||||
pixbuf = pixbuf.scale_simple(x, y, gtk.gdk.INTERP_BILINEAR)
|
||||
self.subpixmap.set_from_pixbuf(pixbuf)
|
||||
self.subpixmap.show()
|
||||
except:
|
||||
self.subpixmap.hide()
|
||||
|
||||
def build_menu_names(self, person):
|
||||
"""
|
||||
Provide the information needed by the base class to define the
|
||||
window management menu entries.
|
||||
"""
|
||||
if self.source:
|
||||
submenu_label = _('Media: %s') % self.source.get_gramps_id()
|
||||
else:
|
||||
submenu_label = _('New Media')
|
||||
return (_('Media Reference Editor'),submenu_label)
|
||||
|
||||
def button_press_event(self, obj, event):
|
||||
if event.button==1 and event.type == gtk.gdk._2BUTTON_PRESS:
|
||||
photo_path = Utils.media_path_full(self.db, self.source.get_path())
|
||||
open_file_with_default_application(photo_path)
|
||||
|
||||
def button_press_event_ref(self, widget, event):
|
||||
"""
|
||||
Handle the button-press-event generated by the eventbox
|
||||
parent of the subpixmap. Remember these coordinates
|
||||
so we can crop the picture when button-release-event
|
||||
is received.
|
||||
"""
|
||||
self.button_press_coords = (event.x, event.y)
|
||||
|
||||
def button_release_event_ref(self, widget, event):
|
||||
"""
|
||||
Handle the button-release-event generated by the eventbox
|
||||
parent of the subpixmap. Crop the picture accordingly.
|
||||
"""
|
||||
|
||||
# reset the crop on double-click or click+CTRL
|
||||
if (event.button==1 and event.type == gtk.gdk._2BUTTON_PRESS) or \
|
||||
(event.button==1 and (event.state & gtk.gdk.CONTROL_MASK) ):
|
||||
self.corner1_x_spinbutton.set_value(0)
|
||||
self.corner1_y_spinbutton.set_value(0)
|
||||
self.corner2_x_spinbutton.set_value(100)
|
||||
self.corner2_y_spinbutton.set_value(100)
|
||||
|
||||
else:
|
||||
|
||||
# ensure the clicks happened at least 5 pixels away from each other
|
||||
new_x1 = min(self.button_press_coords[0], event.x)
|
||||
new_y1 = min(self.button_press_coords[1], event.y)
|
||||
new_x2 = max(self.button_press_coords[0], event.x)
|
||||
new_y2 = max(self.button_press_coords[1], event.y)
|
||||
|
||||
if new_x2 - new_x1 >= 5 and new_y2 - new_y1 >= 5:
|
||||
|
||||
# get the image size and calculate the X and Y offsets
|
||||
# (image is centered when smaller than const.THUMBSCALE)
|
||||
pixbuf = self.subpixmap.get_pixbuf();
|
||||
w = pixbuf.get_width()
|
||||
h = pixbuf.get_height()
|
||||
x = (const.THUMBSCALE - w) / 2
|
||||
y = (const.THUMBSCALE - h) / 2
|
||||
|
||||
# if the click was outside of the image,
|
||||
# bring it within the boundaries
|
||||
if new_x1 < x:
|
||||
new_x1 = x
|
||||
if new_y1 < y:
|
||||
new_y1 = y
|
||||
if new_x2 >= x + w:
|
||||
new_x2 = x + w - 1
|
||||
if new_y2 >= y + h:
|
||||
new_y2 = y + h - 1
|
||||
|
||||
# get the old spinbutton % values
|
||||
old_x1 = self.corner1_x_spinbutton.get_value()
|
||||
old_y1 = self.corner1_y_spinbutton.get_value()
|
||||
old_x2 = self.corner2_x_spinbutton.get_value()
|
||||
old_y2 = self.corner2_y_spinbutton.get_value()
|
||||
delta_x = old_x2 - old_x1 # horizontal scale
|
||||
delta_y = old_y2 - old_y1 # vertical scale
|
||||
|
||||
# Took a while to figure out the math here.
|
||||
#
|
||||
# 1) figure out the current crop % values
|
||||
# by doing the following:
|
||||
#
|
||||
# xp = click_location_x / width * 100
|
||||
# yp = click_location_y / height * 100
|
||||
#
|
||||
# but remember that click_location_x and _y
|
||||
# might not be zero-based for non-rectangular
|
||||
# images, so subtract the pixbuf "x" and "y"
|
||||
# to bring the values back to zero-based
|
||||
#
|
||||
# 2) the minimum value cannot be less than the
|
||||
# existing crop value, so add the current
|
||||
# minimum to the new values
|
||||
|
||||
new_x1 = old_x1 + delta_x * (new_x1 - x) / w
|
||||
new_y1 = old_y1 + delta_y * (new_y1 - y) / h
|
||||
new_x2 = old_x1 + delta_x * (new_x2 - x) / w
|
||||
new_y2 = old_y1 + delta_y * (new_y2 - y) / h
|
||||
|
||||
# set the new values
|
||||
self.corner1_x_spinbutton.set_value(new_x1)
|
||||
self.corner1_y_spinbutton.set_value(new_y1)
|
||||
self.corner2_x_spinbutton.set_value(new_x2)
|
||||
self.corner2_y_spinbutton.set_value(new_y2)
|
||||
|
||||
def _update_addmedia(self, obj):
|
||||
"""
|
||||
Called when the add media dialog has been called.
|
||||
This allows us to update the main form in response to
|
||||
any changes: Redraw relevant fields: description, mimetype and path
|
||||
"""
|
||||
for obj in (self.descr_window, self.path_obj):
|
||||
obj.update()
|
||||
self.draw_preview()
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_cancel_button(self.top.get_object('button84'))
|
||||
self.define_ok_button(self.top.get_object('button82'),self.save)
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('media-rebuild', self.close)
|
||||
self._add_db_signal('media-delete', self.check_for_close)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
Create the notebook tabs and inserts them into the main
|
||||
window.
|
||||
"""
|
||||
notebook_ref = self.top.get_object('notebook_ref')
|
||||
notebook_src = self.top.get_object('notebook_shared')
|
||||
|
||||
self._add_tab(notebook_src, self.primtab)
|
||||
self._add_tab(notebook_ref, self.reftab)
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook_ref,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source_ref))
|
||||
|
||||
self.attr_list = self._add_tab(
|
||||
notebook_ref,
|
||||
AttrEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source_ref.get_attribute_list()))
|
||||
|
||||
self.backref_list = self._add_tab(
|
||||
notebook_src,
|
||||
MediaBackRefList(self.dbstate,self.uistate,self.track,
|
||||
self.db.find_backlink_handles(self.source.handle),
|
||||
self.enable_warnbox
|
||||
))
|
||||
|
||||
self.note_ref_tab = self._add_tab(
|
||||
notebook_ref,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source_ref.get_note_list(),
|
||||
notetype=NoteType.MEDIAREF))
|
||||
|
||||
self.src_srcref_list = self._add_tab(
|
||||
notebook_src,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source))
|
||||
|
||||
self.src_attr_list = self._add_tab(
|
||||
notebook_src,
|
||||
AttrEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source.get_attribute_list()))
|
||||
|
||||
self.src_note_ref_tab = self._add_tab(
|
||||
notebook_src,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_note_list(),
|
||||
notetype=NoteType.MEDIA))
|
||||
|
||||
self._setup_notebook_tabs(notebook_src)
|
||||
self._setup_notebook_tabs(notebook_ref)
|
||||
|
||||
def save(self,*obj):
|
||||
#first save primary object
|
||||
trans = self.db.transaction_begin()
|
||||
if self.source.handle:
|
||||
self.db.commit_media_object(self.source, trans)
|
||||
self.db.transaction_commit(trans, _("Edit Media Object (%s)"
|
||||
) % self.source.get_description())
|
||||
else:
|
||||
self.db.add_object(self.source, trans)
|
||||
self.db.transaction_commit(trans,_("Add Media Object (%s)"
|
||||
) % self.source.get_description())
|
||||
|
||||
#save reference object in memory
|
||||
coord = (
|
||||
self.top.get_object("corner1_x").get_value_as_int(),
|
||||
self.top.get_object("corner1_y").get_value_as_int(),
|
||||
self.top.get_object("corner2_x").get_value_as_int(),
|
||||
self.top.get_object("corner2_y").get_value_as_int(),
|
||||
)
|
||||
|
||||
#do not set unset or invalid coord
|
||||
|
||||
if coord is not None and coord in (
|
||||
(None,)*4,
|
||||
(0, 0, 100, 100),
|
||||
(coord[0], coord[1])*2
|
||||
):
|
||||
coord = None
|
||||
|
||||
self.source_ref.set_rectangle(coord)
|
||||
|
||||
#call callback if given
|
||||
if self.update:
|
||||
self.update(self.source_ref,self.source)
|
||||
|
||||
self.close()
|
||||
417
src/gui/editors/editname.py
Normal file
417
src/gui/editors/editname.py
Normal file
@@ -0,0 +1,417 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# 2008-2009 Benny Malengier
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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 _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from BasicUtils import name_displayer
|
||||
from editsecondary import EditSecondary
|
||||
from gen.lib import NoteType
|
||||
from DisplayTabs import GrampsTab,SourceEmbedList,NoteTab
|
||||
from gui.widgets import (MonitoredEntry, MonitoredMenu, MonitoredDate,
|
||||
MonitoredDataType, PrivacyButton)
|
||||
from glade import Glade
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class GeneralNameTab(GrampsTab):
|
||||
"""
|
||||
This class provides the tabpage of the general name tab
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate, uistate, track, name, widget):
|
||||
"""
|
||||
@param dbstate: The database state. Contains a reference to
|
||||
the database, along with other state information. The GrampsTab
|
||||
uses this to access the database and to pass to and created
|
||||
child windows (such as edit dialogs).
|
||||
@type dbstate: DbState
|
||||
@param uistate: The UI state. Used primarily to pass to any created
|
||||
subwindows.
|
||||
@type uistate: DisplayState
|
||||
@param track: The window tracking mechanism used to manage windows.
|
||||
This is only used to pass to generted child windows.
|
||||
@type track: list
|
||||
@param name: Notebook label name
|
||||
@type name: str/unicode
|
||||
@param widget: widget to be shown in the tab
|
||||
@type widge: gtk widget
|
||||
"""
|
||||
GrampsTab.__init__(self, dbstate, uistate, track, name)
|
||||
eventbox = gtk.EventBox()
|
||||
eventbox.add(widget)
|
||||
self.pack_start(eventbox)
|
||||
self._set_label(show_image=False)
|
||||
widget.connect('key_press_event', self.key_pressed)
|
||||
self.show_all()
|
||||
|
||||
def is_empty(self):
|
||||
"""
|
||||
Override base class
|
||||
"""
|
||||
return False
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditName class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditName(EditSecondary):
|
||||
|
||||
def __init__(self, dbstate, uistate, track, name, callback):
|
||||
|
||||
EditSecondary.__init__(self, dbstate, uistate,
|
||||
track, name, callback)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.name-width'
|
||||
self.height_key = 'interface.name-height'
|
||||
|
||||
self.top = Glade()
|
||||
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object("title"),
|
||||
_("Name Editor"))
|
||||
|
||||
tblgnam = self.top.get_object('table23')
|
||||
notebook = self.top.get_object('notebook')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.gennam = GeneralNameTab(self.dbstate, self.uistate, self.track,
|
||||
_('_General'), tblgnam)
|
||||
|
||||
self.original_group_as = self.obj.get_group_as()
|
||||
self.original_group_set = not (self.original_group_as == '')
|
||||
srn = self.obj.get_surname()
|
||||
self._get_global_grouping(srn)
|
||||
|
||||
self.group_over = self.top.get_object('group_over')
|
||||
self.group_over.connect('toggled',self.on_group_over_toggled)
|
||||
self.group_over.set_sensitive(not self.db.readonly)
|
||||
|
||||
self.toggle_dirty = False
|
||||
|
||||
def _post_init(self):
|
||||
"""if there is override, set the override toggle active
|
||||
"""
|
||||
if self.original_group_set or self.global_group_set :
|
||||
self.group_over.set_active(True)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_cancel_button(self.top.get_object('button119'))
|
||||
self.define_help_button(self.top.get_object('button131'))
|
||||
self.define_ok_button(self.top.get_object('button118'),self.save)
|
||||
|
||||
def _setup_fields(self):
|
||||
self.group_as = MonitoredEntry(
|
||||
self.top.get_object("group_as"),
|
||||
self.obj.set_group_as,
|
||||
self.obj.get_group_as,
|
||||
self.db.readonly)
|
||||
|
||||
if not self.original_group_set:
|
||||
if self.global_group_set :
|
||||
self.group_as.force_value(self.global_group_as)
|
||||
else :
|
||||
self.group_as.force_value(self.obj.get_surname())
|
||||
|
||||
format_list = [(name, number) for (number, name,fmt_str,act)
|
||||
in name_displayer.get_name_format(also_default=True)]
|
||||
|
||||
self.sort_as = MonitoredMenu(
|
||||
self.top.get_object('sort_as'),
|
||||
self.obj.set_sort_as,
|
||||
self.obj.get_sort_as,
|
||||
format_list,
|
||||
self.db.readonly)
|
||||
|
||||
self.display_as = MonitoredMenu(
|
||||
self.top.get_object('display_as'),
|
||||
self.obj.set_display_as,
|
||||
self.obj.get_display_as,
|
||||
format_list,
|
||||
self.db.readonly)
|
||||
|
||||
self.given_field = MonitoredEntry(
|
||||
self.top.get_object("alt_given"),
|
||||
self.obj.set_first_name,
|
||||
self.obj.get_first_name,
|
||||
self.db.readonly)
|
||||
|
||||
self.call_field = MonitoredEntry(
|
||||
self.top.get_object("call"),
|
||||
self.obj.set_call_name,
|
||||
self.obj.get_call_name,
|
||||
self.db.readonly)
|
||||
|
||||
self.title_field = MonitoredEntry(
|
||||
self.top.get_object("alt_title"),
|
||||
self.obj.set_title,
|
||||
self.obj.get_title,
|
||||
self.db.readonly)
|
||||
|
||||
self.suffix_field = MonitoredEntry(
|
||||
self.top.get_object("alt_suffix"),
|
||||
self.obj.set_suffix,
|
||||
self.obj.get_suffix,
|
||||
self.db.readonly)
|
||||
|
||||
self.patronymic_field = MonitoredEntry(
|
||||
self.top.get_object("patronymic"),
|
||||
self.obj.set_patronymic,
|
||||
self.obj.get_patronymic,
|
||||
self.db.readonly)
|
||||
|
||||
self.surname_field = MonitoredEntry(
|
||||
self.top.get_object("alt_surname"),
|
||||
self.obj.set_surname,
|
||||
self.obj.get_surname,
|
||||
self.db.readonly,
|
||||
autolist=self.db.get_surname_list(),
|
||||
changed=self.update_group_as)
|
||||
|
||||
self.prefix_field = MonitoredEntry(
|
||||
self.top.get_object("alt_prefix"),
|
||||
self.obj.set_surname_prefix,
|
||||
self.obj.get_surname_prefix,
|
||||
self.db.readonly)
|
||||
|
||||
self.date = MonitoredDate(
|
||||
self.top.get_object("date_entry"),
|
||||
self.top.get_object("date_stat"),
|
||||
self.obj.get_date_object(),
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.readonly)
|
||||
|
||||
self.obj_combo = MonitoredDataType(
|
||||
self.top.get_object("name_type"),
|
||||
self.obj.set_type,
|
||||
self.obj.get_type,
|
||||
self.db.readonly,
|
||||
self.db.get_name_types(),
|
||||
)
|
||||
|
||||
self.privacy = PrivacyButton(
|
||||
self.top.get_object("priv"), self.obj,
|
||||
self.db.readonly)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
|
||||
notebook = self.top.get_object("notebook")
|
||||
|
||||
self._add_tab(notebook, self.gennam)
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=NoteType.PERSONNAME))
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
|
||||
def _get_global_grouping(self, srn):
|
||||
""" we need info on the global grouping of the surname on init,
|
||||
and on change of surname
|
||||
"""
|
||||
self.global_group_as = self.db.get_name_group_mapping(srn)
|
||||
if srn == self.global_group_as:
|
||||
self.global_group_as = None
|
||||
self.global_group_set = False
|
||||
else:
|
||||
self.global_group_set = True
|
||||
|
||||
|
||||
def build_menu_names(self, name):
|
||||
if name:
|
||||
ntext = name_displayer.display_name(name)
|
||||
submenu_label = '%s: %s' % (_('Name'), ntext)
|
||||
else:
|
||||
submenu_label = _('New Name')
|
||||
menu_label = _('Name Editor')
|
||||
return (menu_label,submenu_label)
|
||||
|
||||
def update_group_as(self, obj):
|
||||
"""Callback if surname changes on GUI
|
||||
If overwrite is not set, we change the group name too
|
||||
"""
|
||||
name = self.obj.get_surname()
|
||||
if not self.group_over.get_active():
|
||||
self.group_as.force_value(name)
|
||||
#new surname, so perhaps now a different grouping?
|
||||
self._get_global_grouping(name)
|
||||
if not self.group_over.get_active() and self.global_group_set :
|
||||
self.group_over.set_active(True)
|
||||
self.group_as.enable(True)
|
||||
self.toggle_dirty = True
|
||||
self.group_as.force_value(self.global_group_as)
|
||||
elif self.group_over.get_active() and self.toggle_dirty:
|
||||
#changing surname caused active group_over in past, change
|
||||
# group_over as we type
|
||||
if self.global_group_set :
|
||||
self.group_as.force_value(self.global_group_as)
|
||||
else:
|
||||
self.toggle_dirty = False
|
||||
self.group_as.force_value(name)
|
||||
self.group_over.set_active(False)
|
||||
self.group_as.enable(False)
|
||||
|
||||
def on_group_over_toggled(self, obj):
|
||||
""" group over changes, if activated, enable edit,
|
||||
if unactivated, go back to surname.
|
||||
"""
|
||||
self.toggle_dirty = False
|
||||
#enable group as box
|
||||
self.group_as.enable(obj.get_active())
|
||||
|
||||
if not obj.get_active():
|
||||
surname = self.obj.get_surname()
|
||||
self.group_as.set_text(surname)
|
||||
|
||||
def save(self,*obj):
|
||||
"""Save the name setting. All is ok, except grouping. We need to
|
||||
consider:
|
||||
1/ global set, not local set --> unset (ask if global unset)
|
||||
2/ global set, local set --> unset (only local unset!)
|
||||
3/ not global set, local set
|
||||
or not global set, not local set --> unset
|
||||
4/ not local set, not global set
|
||||
or not local set, global set --> set val (ask global or local)
|
||||
5/ local set, not global set --> set (change local)
|
||||
6/ local set, global set --> set (set to global if possible)
|
||||
"""
|
||||
closeit = True
|
||||
surname = self.obj.get_surname()
|
||||
group_as= self.obj.get_group_as()
|
||||
grouping_active = self.group_over.get_active()
|
||||
|
||||
if not grouping_active :
|
||||
#user wants to group with surname
|
||||
if self.global_group_set and not self.original_group_set :
|
||||
#warn that group will revert to surname
|
||||
from QuestionDialog import QuestionDialog2
|
||||
q = QuestionDialog2(
|
||||
_("Break global name grouping?"),
|
||||
_("All people with the name of %(surname)s will no longer "
|
||||
"be grouped with the name of %(group_name)s."
|
||||
) % { 'surname' : surname,
|
||||
'group_name':group_as},
|
||||
_("Continue"),
|
||||
_("Return to Name Editor"))
|
||||
val = q.run()
|
||||
if val:
|
||||
#delete the grouping link on database
|
||||
self.db.set_name_group_mapping(surname, None)
|
||||
self.obj.set_group_as("")
|
||||
else :
|
||||
closeit = False
|
||||
elif self.global_group_set and self.original_group_set:
|
||||
#we change it only back to surname locally, so store group_as
|
||||
# Note: if all surnames are locally changed to surname, we
|
||||
# should actually unsed the global group here ....
|
||||
pass
|
||||
else :
|
||||
#global group not set, don't set local group too:
|
||||
self.obj.set_group_as("")
|
||||
else:
|
||||
#user wants to override surname, see what he wants
|
||||
if not self.original_group_set :
|
||||
#if changed, ask if this has to happen for the entire group,
|
||||
#this might be creation of group link, or change of group link
|
||||
if self.global_group_as != group_as:
|
||||
from QuestionDialog import QuestionDialog2
|
||||
|
||||
q = QuestionDialog2(
|
||||
_("Group all people with the same name?"),
|
||||
_("You have the choice of grouping all people with the "
|
||||
"name of %(surname)s with the name of %(group_name)s, or "
|
||||
"just mapping this particular name."
|
||||
) % { 'surname' : surname,
|
||||
'group_name':group_as},
|
||||
_("Group all"),
|
||||
_("Group this name only"))
|
||||
val = q.run()
|
||||
if val:
|
||||
if group_as == surname :
|
||||
self.db.set_name_group_mapping(surname, None)
|
||||
else:
|
||||
self.db.set_name_group_mapping(surname, group_as)
|
||||
self.obj.set_group_as("")
|
||||
else:
|
||||
if self.global_group_set :
|
||||
#allow smith to Dummy, but one person still Smith
|
||||
self.obj.set_group_as(group_as)
|
||||
elif group_as == surname :
|
||||
self.obj.set_group_as("")
|
||||
else:
|
||||
self.obj.set_group_as(group_as)
|
||||
else:
|
||||
#keep original value, no original group
|
||||
self.obj.set_group_as("")
|
||||
elif not self.global_group_set :
|
||||
#don't ask user, group was set locally before,
|
||||
#change it locally only
|
||||
if group_as == surname :
|
||||
#remove grouping
|
||||
self.obj.set_group_as("")
|
||||
else:
|
||||
pass
|
||||
|
||||
else:
|
||||
#locally set group and global group set
|
||||
if group_as == self.global_group_as :
|
||||
#unset local group, go with global one
|
||||
self.obj.set_group_as("")
|
||||
else :
|
||||
#local set is different from global, keep it like that
|
||||
pass
|
||||
|
||||
if closeit:
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
387
src/gui/editors/editnote.py
Normal file
387
src/gui/editors/editnote.py
Normal file
@@ -0,0 +1,387 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
# 2009 Benny Malengier
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
import logging
|
||||
_LOG = logging.getLogger(".gui.editors.EditNote")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK libraries
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
import gobject
|
||||
import pango
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import config
|
||||
import const
|
||||
from gui.widgets import StyledTextEditor
|
||||
from editprimary import EditPrimary
|
||||
from DisplayTabs import GrampsTab, NoteBackRefList
|
||||
from gui.widgets import (MonitoredDataType, MonitoredCheckbox,
|
||||
MonitoredEntry, PrivacyButton)
|
||||
from gen.lib import Note
|
||||
from QuestionDialog import ErrorDialog
|
||||
from glade import Glade
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# NoteTab
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class NoteTab(GrampsTab):
|
||||
"""
|
||||
This class provides the tabpage of the note
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate, uistate, track, name, widget):
|
||||
"""
|
||||
@param dbstate: The database state. Contains a reference to
|
||||
the database, along with other state information. The GrampsTab
|
||||
uses this to access the database and to pass to and created
|
||||
child windows (such as edit dialogs).
|
||||
@type dbstate: L{DbState.DbState}
|
||||
@param uistate: The UI state. Used primarily to pass to any created
|
||||
subwindows.
|
||||
@type uistate: L{DisplayState.DisplayState}
|
||||
@param track: The window tracking mechanism used to manage windows.
|
||||
This is only used to pass to generted child windows.
|
||||
@type track: list
|
||||
@param name: Notebook label name
|
||||
@type name: str/unicode
|
||||
@param widget: widget to be shown in the tab
|
||||
@type widget: gtk widget
|
||||
"""
|
||||
GrampsTab.__init__(self, dbstate, uistate, track, name)
|
||||
eventbox = gtk.EventBox()
|
||||
eventbox.add(widget)
|
||||
self.pack_start(eventbox)
|
||||
self._set_label(show_image=False)
|
||||
eventbox.connect('key_press_event', self.key_pressed)
|
||||
self.show_all()
|
||||
|
||||
def is_empty(self):
|
||||
"""
|
||||
Override base class
|
||||
"""
|
||||
return False
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditNote
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class EditNote(EditPrimary):
|
||||
def __init__(self, dbstate, uistate, track, note, callback=None,
|
||||
callertitle = None, extratype = None):
|
||||
"""Create an EditNote window. Associate a note with the window.
|
||||
|
||||
@param callertitle: Text passed by calling object to add to title
|
||||
@type callertitle: str
|
||||
@param extratype: Extra L{NoteType} values to add to the default types.
|
||||
They are removed from the ignorelist of L{NoteType}.
|
||||
@type extratype: list of int
|
||||
|
||||
"""
|
||||
self.callertitle = callertitle
|
||||
self.extratype = extratype
|
||||
EditPrimary.__init__(self, dbstate, uistate, track, note,
|
||||
dbstate.db.get_note_from_handle,
|
||||
dbstate.db.get_note_from_gramps_id, callback)
|
||||
|
||||
def empty_object(self):
|
||||
"""Return an empty Note object for comparison for changes.
|
||||
|
||||
It is used by the base class L{EditPrimary}.
|
||||
|
||||
"""
|
||||
empty_note = Note();
|
||||
if self.extratype:
|
||||
empty_note.set_type(self.extratype[0])
|
||||
return empty_note
|
||||
|
||||
def get_menu_title(self):
|
||||
if self.obj.get_handle():
|
||||
if self.callertitle :
|
||||
title = _('Note: %(id)s - %(context)s') % {
|
||||
'id' : self.obj.get_gramps_id(),
|
||||
'context' : self.callertitle
|
||||
}
|
||||
else :
|
||||
title = _('Note: %s') % self.obj.get_gramps_id()
|
||||
else:
|
||||
if self.callertitle :
|
||||
title = _('New Note - %(context)s') % {
|
||||
'context' : self.callertitle
|
||||
}
|
||||
else :
|
||||
title = _('New Note')
|
||||
|
||||
return title
|
||||
|
||||
def get_custom_notetypes(self):
|
||||
return self.dbstate.db.get_note_types()
|
||||
|
||||
def _local_init(self):
|
||||
"""Local initialization function.
|
||||
|
||||
Perform basic initialization, including setting up widgets
|
||||
and the glade interface. It is called by the base class L{EditPrimary},
|
||||
and overridden here.
|
||||
|
||||
"""
|
||||
self.width_key = 'interface.note-width'
|
||||
self.height_key = 'interface.note-height'
|
||||
|
||||
self.top = Glade()
|
||||
|
||||
win = self.top.toplevel
|
||||
self.set_window(win, None, self.get_menu_title())
|
||||
|
||||
|
||||
vboxnote = self.top.get_object('vbox131')
|
||||
notebook = self.top.get_object('note_notebook')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.ntab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
_('_Note'), vboxnote)
|
||||
self.track_ref_for_deletion("ntab")
|
||||
|
||||
self.build_interface()
|
||||
|
||||
def _setup_fields(self):
|
||||
"""Get control widgets and attach them to Note's attributes."""
|
||||
self.type_selector = MonitoredDataType(
|
||||
self.top.get_object('type'),
|
||||
self.obj.set_type,
|
||||
self.obj.get_type,
|
||||
self.db.readonly,
|
||||
custom_values=self.get_custom_notetypes(),
|
||||
ignore_values=self.obj.get_type().get_ignore_list(self.extratype))
|
||||
|
||||
self.check = MonitoredCheckbox(
|
||||
self.obj,
|
||||
self.top.get_object('format'),
|
||||
self.obj.set_format,
|
||||
self.obj.get_format,
|
||||
readonly = self.db.readonly)
|
||||
|
||||
self.gid = MonitoredEntry(
|
||||
self.top.get_object('id'),
|
||||
self.obj.set_gramps_id,
|
||||
self.obj.get_gramps_id,
|
||||
self.db.readonly)
|
||||
|
||||
self.marker = MonitoredDataType(
|
||||
self.top.get_object('marker'),
|
||||
self.obj.set_marker,
|
||||
self.obj.get_marker,
|
||||
self.db.readonly,
|
||||
self.db.get_marker_types())
|
||||
|
||||
self.priv = PrivacyButton(
|
||||
self.top.get_object("private"),
|
||||
self.obj, self.db.readonly)
|
||||
|
||||
def _connect_signals(self):
|
||||
"""Connects any signals that need to be connected.
|
||||
|
||||
Called by the init routine of the base class L{EditPrimary}.
|
||||
|
||||
"""
|
||||
self.define_ok_button(self.top.get_object('ok'), self.save)
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
self.define_help_button(self.top.get_object('help'))
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('note-rebuild', self._do_close)
|
||||
self._add_db_signal('note-delete', self.check_for_close)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""Create the notebook tabs and inserts them into the main window."""
|
||||
notebook = self.top.get_object("note_notebook")
|
||||
|
||||
self._add_tab(notebook, self.ntab)
|
||||
|
||||
handles = self.dbstate.db.find_backlink_handles(self.obj.handle)
|
||||
self.rlist = NoteBackRefList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
handles)
|
||||
self.backref_tab = self._add_tab(notebook, self.rlist)
|
||||
self.track_ref_for_deletion("rlist")
|
||||
self.track_ref_for_deletion("backref_tab")
|
||||
|
||||
self._setup_notebook_tabs(notebook)
|
||||
|
||||
def build_interface(self):
|
||||
self.texteditor = self.top.get_object('texteditor')
|
||||
self.texteditor.set_editable(not self.dbstate.db.readonly)
|
||||
self.texteditor.set_wrap_mode(gtk.WRAP_WORD)
|
||||
|
||||
# create a formatting toolbar
|
||||
if not self.dbstate.db.readonly:
|
||||
vbox = self.top.get_object('container')
|
||||
vbox.pack_start(self.texteditor.get_toolbar(),
|
||||
expand=False, fill=False)
|
||||
|
||||
# setup initial values for textview and textbuffer
|
||||
if self.obj:
|
||||
self.empty = False
|
||||
self.texteditor.set_text(self.obj.get_styledtext())
|
||||
_LOG.debug("Initial Note: %s" % str(self.texteditor.get_text()))
|
||||
else:
|
||||
self.empty = True
|
||||
|
||||
def build_menu_names(self, person):
|
||||
"""
|
||||
Provide the information needed by the base class to define the
|
||||
window management menu entries.
|
||||
"""
|
||||
return (_('Edit Note'), self.get_menu_title())
|
||||
|
||||
def _post_init(self):
|
||||
self.texteditor.grab_focus()
|
||||
|
||||
def update_note(self):
|
||||
"""Update the Note object with current value."""
|
||||
if self.obj:
|
||||
text = self.texteditor.get_text()
|
||||
self.obj.set_styledtext(text)
|
||||
_LOG.debug(str(text))
|
||||
|
||||
def save(self, *obj):
|
||||
"""Save the data."""
|
||||
self.ok_button.set_sensitive(False)
|
||||
|
||||
self.update_note()
|
||||
|
||||
if self.object_is_empty():
|
||||
ErrorDialog(_("Cannot save note"),
|
||||
_("No data exists for this note. Please "
|
||||
"enter data or cancel the edit."))
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
(uses_dupe_id, id) = self._uses_duplicate_id()
|
||||
if uses_dupe_id:
|
||||
msg1 = _("Cannot save note. ID already exists.")
|
||||
msg2 = _("You have attempted to use the existing Gramps ID with "
|
||||
"value %(id)s. This value is already used. Please "
|
||||
"enter a different ID or leave "
|
||||
"blank to get the next available ID value.") % {
|
||||
'id' : id }
|
||||
ErrorDialog(msg1, msg2)
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
trans = self.db.transaction_begin()
|
||||
|
||||
if not self.obj.get_handle():
|
||||
self.db.add_note(self.obj, trans)
|
||||
msg = _("Add Note")
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_note_gramps_id())
|
||||
self.db.commit_note(self.obj, trans)
|
||||
msg = _("Edit Note")
|
||||
|
||||
self.db.transaction_commit(trans, msg)
|
||||
|
||||
if self.callback:
|
||||
self.callback(self.obj.get_handle())
|
||||
self.close()
|
||||
|
||||
class DeleteNoteQuery(object):
|
||||
def __init__(self, dbstate, uistate, note, the_lists):
|
||||
self.note = note
|
||||
self.db = dbstate.db
|
||||
self.uistate = uistate
|
||||
self.the_lists = the_lists
|
||||
|
||||
def query_response(self):
|
||||
trans = self.db.transaction_begin()
|
||||
self.db.disable_signals()
|
||||
|
||||
(person_list, family_list, event_list, place_list, source_list,
|
||||
media_list, repo_list) = self.the_lists
|
||||
|
||||
note_handle = self.note.get_handle()
|
||||
|
||||
for handle in person_list:
|
||||
person = self.db.get_person_from_handle(handle)
|
||||
person.remove_note(note_handle)
|
||||
self.db.commit_person(person, trans)
|
||||
|
||||
for handle in family_list:
|
||||
family = self.db.get_family_from_handle(handle)
|
||||
family.remove_note(note_handle)
|
||||
self.db.commit_family(family, trans)
|
||||
|
||||
for handle in event_list:
|
||||
event = self.db.get_event_from_handle(handle)
|
||||
event.remove_note(note_handle)
|
||||
self.db.commit_event(event, trans)
|
||||
|
||||
for handle in place_list:
|
||||
place = self.db.get_place_from_handle(handle)
|
||||
place.remove_note(note_handle)
|
||||
self.db.commit_place(place, trans)
|
||||
|
||||
for handle in source_list:
|
||||
source = self.db.get_source_from_handle(handle)
|
||||
source.remove_note(note_handle)
|
||||
self.db.commit_source(source, trans)
|
||||
|
||||
for handle in media_list:
|
||||
media = self.db.get_object_from_handle(handle)
|
||||
media.remove_note(note_handle)
|
||||
self.db.commit_media_object(media, trans)
|
||||
|
||||
for handle in repo_list:
|
||||
repo = self.db.get_repository_from_handle(handle)
|
||||
repo.remove_note(note_handle)
|
||||
self.db.commit_repository(repo, trans)
|
||||
|
||||
self.db.enable_signals()
|
||||
self.db.remove_note(note_handle, trans)
|
||||
self.db.transaction_commit(
|
||||
trans,_("Delete Note (%s)") % self.note.get_gramps_id())
|
||||
915
src/gui/editors/editperson.py
Normal file
915
src/gui/editors/editperson.py
Normal file
@@ -0,0 +1,915 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
"""
|
||||
EditPerson Dialog. Provide the interface to allow the GRAMPS program
|
||||
to edit information about a particular Person.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import locale
|
||||
from TransUtils import sgettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
import Utils
|
||||
from gui.utils import add_menuitem, open_file_with_default_application
|
||||
import Mime
|
||||
import gen.lib
|
||||
from gui import widgets
|
||||
from BasicUtils import name_displayer
|
||||
import Errors
|
||||
from glade import Glade
|
||||
from gen.utils import set_birth_death_index
|
||||
|
||||
from editprimary import EditPrimary
|
||||
from editmediaref import EditMediaRef
|
||||
from editname import EditName
|
||||
import config
|
||||
from QuestionDialog import ErrorDialog, ICON
|
||||
|
||||
from DisplayTabs import (PersonEventEmbedList, NameEmbedList, SourceEmbedList,
|
||||
AttrEmbedList, AddrEmbedList, NoteTab, GalleryTab,
|
||||
WebEmbedList, PersonRefEmbedList, LdsEmbedList,
|
||||
PersonBackRefList)
|
||||
from gen.plug import CATEGORY_QR_PERSON
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
_select_gender = ((True, False, False),
|
||||
(False, True, False),
|
||||
(False, False, True))
|
||||
|
||||
class EditPerson(EditPrimary):
|
||||
"""
|
||||
The EditPerson dialog is derived from the EditPrimary class.
|
||||
|
||||
It allows for the editing of the primary object type of Person.
|
||||
|
||||
"""
|
||||
|
||||
QR_CATEGORY = CATEGORY_QR_PERSON
|
||||
|
||||
def __init__(self, dbstate, uistate, track, person, callback=None):
|
||||
"""
|
||||
Create an EditPerson window.
|
||||
|
||||
Associate a person with the window.
|
||||
|
||||
"""
|
||||
EditPrimary.__init__(self, dbstate, uistate, track, person,
|
||||
dbstate.db.get_person_from_handle,
|
||||
dbstate.db.get_person_from_gramps_id, callback)
|
||||
|
||||
def empty_object(self):
|
||||
"""
|
||||
Return an empty Person object for comparison for changes.
|
||||
|
||||
This is used by the base class (EditPrimary).
|
||||
|
||||
"""
|
||||
return gen.lib.Person()
|
||||
|
||||
def get_menu_title(self):
|
||||
if self.obj.get_handle():
|
||||
name = name_displayer.display(self.obj)
|
||||
title = _('Person: %(name)s') % {'name': name}
|
||||
else:
|
||||
name = name_displayer.display(self.obj)
|
||||
if name:
|
||||
title = _('New Person: %(name)s') % {'name': name}
|
||||
else:
|
||||
title = _('New Person')
|
||||
return title
|
||||
|
||||
def _local_init(self):
|
||||
"""
|
||||
Performs basic initialization, including setting up widgets and the
|
||||
glade interface.
|
||||
|
||||
Local initialization function.
|
||||
This is called by the base class of EditPrimary, and overridden here.
|
||||
|
||||
"""
|
||||
self.width_key = 'interface.person-width'
|
||||
self.height_key = 'interface.person-height'
|
||||
self.pname = self.obj.get_primary_name()
|
||||
self.should_guess_gender = (not self.obj.get_gramps_id() and
|
||||
self.obj.get_gender () ==
|
||||
gen.lib.Person.UNKNOWN)
|
||||
|
||||
self.load_obj = None
|
||||
self.load_rect = None
|
||||
self.top = Glade()
|
||||
|
||||
self.set_window(self.top.toplevel, None,
|
||||
self.get_menu_title())
|
||||
|
||||
self.obj_photo = self.top.get_object("personPix")
|
||||
self.eventbox = self.top.get_object("eventbox1")
|
||||
|
||||
self.set_contexteventbox(self.top.get_object("eventboxtop"))
|
||||
|
||||
|
||||
def _post_init(self):
|
||||
"""
|
||||
Handle any initialization that needs to be done after the interface is
|
||||
brought up.
|
||||
|
||||
Post initalization function.
|
||||
This is called by _EditPrimary's init routine, and overridden in the
|
||||
derived class (this class).
|
||||
|
||||
"""
|
||||
self.load_person_image()
|
||||
if self.pname.get_surname() and not self.pname.get_first_name():
|
||||
self.given.grab_focus()
|
||||
else:
|
||||
self.surname_field.grab_focus()
|
||||
|
||||
def _connect_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self.define_cancel_button(self.top.get_object("button15"))
|
||||
self.define_ok_button(self.top.get_object("ok"), self.save)
|
||||
self.define_help_button(self.top.get_object("button134"))
|
||||
|
||||
self.given.connect("focus_out_event", self._given_focus_out_event)
|
||||
self.top.get_object("button177").connect("clicked",
|
||||
self._edit_name_clicked)
|
||||
|
||||
self.eventbox.connect('button-press-event',
|
||||
self._image_button_press)
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('person-rebuild', self._do_close)
|
||||
self._add_db_signal('person-delete', self.check_for_close)
|
||||
self._add_db_signal('family-rebuild', self.family_change)
|
||||
self._add_db_signal('family-delete', self.family_change)
|
||||
self._add_db_signal('family-update', self.family_change)
|
||||
self._add_db_signal('family-add', self.family_change)
|
||||
self._add_db_signal('event-update', self.event_updated)
|
||||
self._add_db_signal('event-rebuild', self.event_updated)
|
||||
self._add_db_signal('event-delete', self.event_updated)
|
||||
|
||||
def family_change(self, handle_list=[]):
|
||||
"""
|
||||
Callback for family change signals.
|
||||
|
||||
This should rebuild the
|
||||
backreferences to family in person when:
|
||||
1)a family the person is parent of changes. Person could have
|
||||
been removed
|
||||
2)a family the person is child in changes. Child could have been
|
||||
removed
|
||||
3)a family is changed. The person could be added as child or
|
||||
parent
|
||||
|
||||
"""
|
||||
#As this would be an extensive check, we choose the easy path and
|
||||
# rebuild family backreferences on all family changes
|
||||
self._update_families()
|
||||
|
||||
def _update_families(self):
|
||||
phandle = self.obj.get_handle()
|
||||
if phandle:
|
||||
#new person has no handle yet and cannot be in a family.
|
||||
person = self.dbstate.db.get_person_from_handle(phandle)
|
||||
self.obj.set_family_handle_list(person.get_family_handle_list())
|
||||
self.obj.set_parent_family_handle_list(
|
||||
person.get_parent_family_handle_list())
|
||||
#a family groupname in event_list might need to be changed
|
||||
# we just rebuild the view always
|
||||
self.event_list.rebuild_callback()
|
||||
|
||||
def event_updated(self, obj):
|
||||
#place in event might have changed, or person event shown in the list
|
||||
# we just rebuild the view always
|
||||
self.event_list.rebuild_callback()
|
||||
|
||||
def _setup_fields(self):
|
||||
"""
|
||||
Connect the GrampsWidget objects to field in the interface.
|
||||
|
||||
This allows the widgets to keep the data in the attached Person object
|
||||
up to date at all times, eliminating a lot of need in 'save' routine.
|
||||
|
||||
"""
|
||||
|
||||
self.private = widgets.PrivacyButton(
|
||||
self.top.get_object('private'),
|
||||
self.obj,
|
||||
self.db.readonly)
|
||||
|
||||
self.gender = widgets.MonitoredMenu(
|
||||
self.top.get_object('gender'),
|
||||
self.obj.set_gender,
|
||||
self.obj.get_gender,
|
||||
(
|
||||
(_('female'), gen.lib.Person.FEMALE),
|
||||
(_('male'), gen.lib.Person.MALE),
|
||||
(_('unknown'), gen.lib.Person.UNKNOWN)
|
||||
),
|
||||
self.db.readonly)
|
||||
|
||||
self.marker = widgets.MonitoredDataType(
|
||||
self.top.get_object('marker'),
|
||||
self.obj.set_marker,
|
||||
self.obj.get_marker,
|
||||
self.db.readonly,
|
||||
self.db.get_marker_types(),
|
||||
)
|
||||
|
||||
self.ntype_field = widgets.MonitoredDataType(
|
||||
self.top.get_object("ntype"),
|
||||
self.pname.set_type,
|
||||
self.pname.get_type,
|
||||
self.db.readonly,
|
||||
self.db.get_name_types())
|
||||
|
||||
self.prefix_suffix = widgets.MonitoredComboSelectedEntry(
|
||||
self.top.get_object("prefixcmb"),
|
||||
self.top.get_object("prefixentry"),
|
||||
[_('Prefix'), _('Suffix')],
|
||||
[self.pname.set_surname_prefix, self.pname.set_suffix],
|
||||
[self.pname.get_surname_prefix, self.pname.get_suffix],
|
||||
default = config.get('interface.prefix-suffix'),
|
||||
read_only = self.db.readonly)
|
||||
|
||||
self.patro_title = widgets.MonitoredComboSelectedEntry(
|
||||
self.top.get_object("patrocmb"),
|
||||
self.top.get_object("patroentry"),
|
||||
[_('Patronymic'), _('Person|Title')],
|
||||
[self.pname.set_patronymic, self.pname.set_title],
|
||||
[self.pname.get_patronymic, self.pname.get_title],
|
||||
default = config.get('interface.patro-title'),
|
||||
read_only = self.db.readonly)
|
||||
|
||||
self.call = widgets.MonitoredEntry(
|
||||
self.top.get_object("call"),
|
||||
self.pname.set_call_name,
|
||||
self.pname.get_call_name,
|
||||
self.db.readonly)
|
||||
|
||||
self.given = widgets.MonitoredEntry(
|
||||
self.top.get_object("given_name"),
|
||||
self.pname.set_first_name,
|
||||
self.pname.get_first_name,
|
||||
self.db.readonly)
|
||||
|
||||
self.surname_field = widgets.MonitoredEntry(
|
||||
self.top.get_object("surname"),
|
||||
self.pname.set_surname,
|
||||
self.pname.get_surname,
|
||||
self.db.readonly,
|
||||
autolist=self.db.get_surname_list())
|
||||
|
||||
self.gid = widgets.MonitoredEntry(
|
||||
self.top.get_object("gid"),
|
||||
self.obj.set_gramps_id,
|
||||
self.obj.get_gramps_id,
|
||||
self.db.readonly)
|
||||
|
||||
#make sure title updates automatically
|
||||
for obj in [self.top.get_object("surname"),
|
||||
self.top.get_object("given_name"),
|
||||
self.top.get_object("patroentry"),
|
||||
self.top.get_object("call"),
|
||||
self.top.get_object("prefixentry"),
|
||||
]:
|
||||
obj.connect('changed', self._changed_name)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
Create the notebook tabs and insert them into the main window.
|
||||
"""
|
||||
notebook = gtk.Notebook()
|
||||
notebook.set_scrollable(True)
|
||||
|
||||
self.event_list = PersonEventEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj)
|
||||
self._add_tab(notebook, self.event_list)
|
||||
self.track_ref_for_deletion("event_list")
|
||||
|
||||
self.name_list = NameEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_alternate_names(),
|
||||
self.obj,
|
||||
self.name_callback)
|
||||
self._add_tab(notebook, self.name_list)
|
||||
self.track_ref_for_deletion("name_list")
|
||||
|
||||
self.srcref_list = SourceEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj)
|
||||
self._add_tab(notebook, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.attr_list = AttrEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_attribute_list())
|
||||
self._add_tab(notebook, self.attr_list)
|
||||
self.track_ref_for_deletion("attr_list")
|
||||
|
||||
self.addr_list = AddrEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_address_list())
|
||||
self._add_tab(notebook, self.addr_list)
|
||||
self.track_ref_for_deletion("addr_list")
|
||||
|
||||
self.note_tab = NoteTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_note_list(),
|
||||
self.get_menu_title(),
|
||||
notetype=gen.lib.NoteType.PERSON)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self.gallery_tab = GalleryTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_media_list(),
|
||||
self.load_person_image)
|
||||
self._add_tab(notebook, self.gallery_tab)
|
||||
self.track_ref_for_deletion("gallery_tab")
|
||||
|
||||
self.web_list = WebEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_url_list())
|
||||
self._add_tab(notebook, self.web_list)
|
||||
self.track_ref_for_deletion("web_list")
|
||||
|
||||
self.person_ref_list = PersonRefEmbedList(self.dbstate, self.uistate,
|
||||
self.track,
|
||||
self.obj.get_person_ref_list())
|
||||
self._add_tab(notebook, self.person_ref_list)
|
||||
self.track_ref_for_deletion("person_ref_list")
|
||||
|
||||
self.lds_list = LdsEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_lds_ord_list())
|
||||
self._add_tab(notebook, self.lds_list)
|
||||
self.track_ref_for_deletion("lds_list")
|
||||
|
||||
self.backref_tab = PersonBackRefList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.find_backlink_handles(self.obj.handle))
|
||||
self._add_tab(notebook, self.backref_tab)
|
||||
self.track_ref_for_deletion("backref_tab")
|
||||
|
||||
self._setup_notebook_tabs(notebook)
|
||||
notebook.show_all()
|
||||
self.top.get_object('vbox').pack_start(notebook, True)
|
||||
|
||||
def _changed_name(self, obj):
|
||||
"""
|
||||
callback to changes typed by user to the person name.
|
||||
Update the window title, and default name in name tab
|
||||
"""
|
||||
self.update_title(self.get_menu_title())
|
||||
self.name_list.update_defname()
|
||||
|
||||
def name_callback(self):
|
||||
"""
|
||||
Callback if changes happen in the name tab that impact the preferred
|
||||
name.
|
||||
"""
|
||||
self.pname = self.obj.get_primary_name()
|
||||
|
||||
self.ntype_field.reinit(self.pname.set_type, self.pname.get_type)
|
||||
|
||||
self.prefix_suffix.reinit(
|
||||
[self.pname.set_surname_prefix, self.pname.set_suffix],
|
||||
[self.pname.get_surname_prefix, self.pname.get_suffix])
|
||||
|
||||
self.call.reinit(
|
||||
self.pname.set_call_name,
|
||||
self.pname.get_call_name)
|
||||
|
||||
self.given.reinit(
|
||||
self.pname.set_first_name,
|
||||
self.pname.get_first_name)
|
||||
|
||||
self.patro_title.reinit(
|
||||
[self.pname.set_patronymic, self.pname.set_title],
|
||||
[self.pname.get_patronymic, self.pname.get_title])
|
||||
|
||||
self.surname_field.reinit(
|
||||
self.pname.set_surname,
|
||||
self.pname.get_surname)
|
||||
|
||||
def build_menu_names(self, person):
|
||||
"""
|
||||
Provide the information needed by the base class to define the
|
||||
window management menu entries.
|
||||
"""
|
||||
return (_('Edit Person'), self.get_menu_title())
|
||||
|
||||
def _image_callback(self, ref, obj):
|
||||
"""
|
||||
Called when a media reference had been edited.
|
||||
|
||||
This allows for the updating image on the main form which has just
|
||||
been modified.
|
||||
|
||||
"""
|
||||
self.load_photo(Utils.media_path_full(self.dbstate.db, obj.get_path()),
|
||||
ref.get_rectangle())
|
||||
|
||||
def _image_button_press(self, obj, event):
|
||||
"""
|
||||
Button press event that is caught when a button has been pressed while
|
||||
on the image on the main form.
|
||||
|
||||
This does not apply to the images in galleries, just the image on the
|
||||
main form.
|
||||
|
||||
"""
|
||||
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
|
||||
|
||||
media_list = self.obj.get_media_list()
|
||||
if media_list:
|
||||
media_ref = media_list[0]
|
||||
object_handle = media_ref.get_reference_handle()
|
||||
media_obj = self.db.get_object_from_handle(object_handle)
|
||||
|
||||
try:
|
||||
EditMediaRef(self.dbstate, self.uistate, self.track,
|
||||
media_obj, media_ref, self._image_callback)
|
||||
except Errors.WindowActiveError:
|
||||
pass
|
||||
|
||||
elif event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
|
||||
media_list = self.obj.get_media_list()
|
||||
if media_list:
|
||||
photo = media_list[0]
|
||||
self._show_popup(photo, event)
|
||||
#do not propagate further:
|
||||
return True
|
||||
|
||||
def _show_popup(self, photo, event):
|
||||
"""
|
||||
Look for right-clicks on a picture and create a popup menu of the
|
||||
available actions.
|
||||
"""
|
||||
|
||||
menu = gtk.Menu()
|
||||
menu.set_title(_("Media Object"))
|
||||
obj = self.db.get_object_from_handle(photo.get_reference_handle())
|
||||
if obj:
|
||||
add_menuitem(menu, _("View"), photo, self._popup_view_photo)
|
||||
add_menuitem(menu, _("Edit Object Properties"), photo,
|
||||
self._popup_change_description)
|
||||
menu.popup(None, None, None, event.button, event.time)
|
||||
|
||||
def _popup_view_photo(self, obj):
|
||||
"""
|
||||
Open this picture in the default picture viewer.
|
||||
"""
|
||||
media_list = self.obj.get_media_list()
|
||||
if media_list:
|
||||
photo = media_list[0]
|
||||
object_handle = photo.get_reference_handle()
|
||||
ref_obj = self.db.get_object_from_handle(object_handle)
|
||||
photo_path = Utils.media_path_full(self.db, ref_obj.get_path())
|
||||
open_file_with_default_application(photo_path)
|
||||
|
||||
def _popup_change_description(self, obj):
|
||||
"""
|
||||
Bring up the EditMediaRef dialog for the image on the main form.
|
||||
"""
|
||||
media_list = self.obj.get_media_list()
|
||||
if media_list:
|
||||
media_ref = media_list[0]
|
||||
object_handle = media_ref.get_reference_handle()
|
||||
media_obj = self.db.get_object_from_handle(object_handle)
|
||||
EditMediaRef(self.dbstate, self.uistate, self.track,
|
||||
media_obj, media_ref, self._image_callback)
|
||||
|
||||
def _top_contextmenu(self):
|
||||
"""
|
||||
Override from base class, the menuitems and actiongroups for the top
|
||||
of context menu.
|
||||
"""
|
||||
self.all_action = gtk.ActionGroup("/PersonAll")
|
||||
self.home_action = gtk.ActionGroup("/PersonHome")
|
||||
self.track_ref_for_deletion("all_action")
|
||||
self.track_ref_for_deletion("home_action")
|
||||
|
||||
self.all_action.add_actions([
|
||||
('ActivePerson', gtk.STOCK_APPLY, _("Make Active Person"),
|
||||
None, None, self._make_active),
|
||||
])
|
||||
self.home_action.add_actions([
|
||||
('HomePerson', gtk.STOCK_HOME, _("Make Home Person"),
|
||||
None, None, self._make_home_person),
|
||||
])
|
||||
|
||||
self.all_action.set_visible(True)
|
||||
self.home_action.set_visible(True)
|
||||
|
||||
ui_top_cm = '''
|
||||
<menuitem action="ActivePerson"/>
|
||||
<menuitem action="HomePerson"/>'''
|
||||
|
||||
return ui_top_cm, [self.all_action, self.home_action]
|
||||
|
||||
def _post_build_popup_ui(self):
|
||||
"""
|
||||
Override base class, make inactive home action if not needed.
|
||||
"""
|
||||
if self.dbstate.db.get_default_person() and \
|
||||
self.obj.get_handle() == \
|
||||
self.dbstate.db.get_default_person().get_handle():
|
||||
self.home_action.set_sensitive(False)
|
||||
else :
|
||||
self.home_action.set_sensitive(True)
|
||||
|
||||
def _make_active(self, obj):
|
||||
self.dbstate.change_active_person(self.obj)
|
||||
|
||||
def _make_home_person(self, obj):
|
||||
handle = self.obj.get_handle()
|
||||
if handle:
|
||||
self.dbstate.db.set_default_person_handle(handle)
|
||||
|
||||
def _given_focus_out_event (self, entry, event):
|
||||
"""
|
||||
Callback that occurs when the user leaves the given name field,
|
||||
allowing us to attempt to guess the gender of the person if
|
||||
so requested.
|
||||
"""
|
||||
if not self.should_guess_gender:
|
||||
return False
|
||||
try:
|
||||
gender_type = self.db.genderStats.guess_gender(
|
||||
unicode(entry.get_text()))
|
||||
self.gender.force(gender_type)
|
||||
except:
|
||||
return False
|
||||
return False
|
||||
|
||||
def load_photo(self, path, rectangle=None):
|
||||
"""
|
||||
Load, scale and display the person's main photo from the path.
|
||||
"""
|
||||
self.load_obj = path
|
||||
self.load_rect = rectangle
|
||||
if path is None:
|
||||
self.obj_photo.hide()
|
||||
else:
|
||||
try:
|
||||
i = gtk.gdk.pixbuf_new_from_file(path)
|
||||
width = i.get_width()
|
||||
height = i.get_height()
|
||||
|
||||
if rectangle is not None:
|
||||
upper_x = min(rectangle[0], rectangle[2])/100.
|
||||
lower_x = max(rectangle[0], rectangle[2])/100.
|
||||
upper_y = min(rectangle[1], rectangle[3])/100.
|
||||
lower_y = max(rectangle[1], rectangle[3])/100.
|
||||
sub_x = int(upper_x * width)
|
||||
sub_y = int(upper_y * height)
|
||||
sub_width = int((lower_x - upper_x) * width)
|
||||
sub_height = int((lower_y - upper_y) * height)
|
||||
if sub_width > 0 and sub_height > 0:
|
||||
i = i.subpixbuf(sub_x, sub_y, sub_width, sub_height)
|
||||
|
||||
ratio = float(max(i.get_height(), i.get_width()))
|
||||
scale = float(100.0)/ratio
|
||||
x = int(scale*(i.get_width()))
|
||||
y = int(scale*(i.get_height()))
|
||||
i = i.scale_simple(x, y, gtk.gdk.INTERP_BILINEAR)
|
||||
self.obj_photo.set_from_pixbuf(i)
|
||||
self.obj_photo.show()
|
||||
except:
|
||||
self.obj_photo.hide()
|
||||
|
||||
def _check_for_unknown_gender(self):
|
||||
if self.obj.get_gender() == gen.lib.Person.UNKNOWN:
|
||||
d = GenderDialog(self.window)
|
||||
gender = d.run()
|
||||
d.destroy()
|
||||
if gender >= 0:
|
||||
self.obj.set_gender(gender)
|
||||
|
||||
def _update_family_ids(self):
|
||||
# Update each of the families child lists to reflect any
|
||||
# change in ordering due to the new birth date
|
||||
family = self.obj.get_main_parents_family_handle()
|
||||
if (family):
|
||||
f = self.db.get_family_from_handle(family)
|
||||
new_order = self.reorder_child_ref_list(self.obj,
|
||||
f.get_child_ref_list())
|
||||
f.set_child_ref_list(new_order)
|
||||
for family in self.obj.get_parent_family_handle_list():
|
||||
f = self.db.get_family_from_handle(family)
|
||||
new_order = self.reorder_child_ref_list(self.obj,
|
||||
f.get_child_ref_list())
|
||||
f.set_child_ref_list(new_order)
|
||||
|
||||
error = False
|
||||
original = self.db.get_person_from_handle(self.obj.handle)
|
||||
|
||||
if original:
|
||||
(female, male, unknown) = _select_gender[self.obj.get_gender()]
|
||||
if male and original.get_gender() != gen.lib.Person.MALE:
|
||||
for tmp_handle in self.obj.get_family_handle_list():
|
||||
temp_family = self.db.get_family_from_handle(tmp_handle)
|
||||
if self.obj == temp_family.get_mother_handle():
|
||||
if temp_family.get_father_handle() is not None:
|
||||
error = True
|
||||
else:
|
||||
temp_family.set_mother_handle(None)
|
||||
temp_family.set_father_handle(self.obj)
|
||||
elif female and original != gen.lib.Person.FEMALE:
|
||||
for tmp_handle in self.obj.get_family_handle_list():
|
||||
temp_family = self.db.get_family_from_handle(tmp_handle)
|
||||
if self.obj == temp_family.get_father_handle():
|
||||
if temp_family.get_mother_handle() is not None:
|
||||
error = True
|
||||
else:
|
||||
temp_family.set_father_handle(None)
|
||||
temp_family.set_mother_handle(self.obj)
|
||||
elif unknown and original.get_gender() != gen.lib.Person.UNKNOWN:
|
||||
for tmp_handle in self.obj.get_family_handle_list():
|
||||
temp_family = self.db.get_family_from_handle(tmp_handle)
|
||||
if self.obj == temp_family.get_father_handle():
|
||||
if temp_family.get_mother_handle() is not None:
|
||||
error = True
|
||||
else:
|
||||
temp_family.set_father_handle(None)
|
||||
temp_family.set_mother_handle(self.obj)
|
||||
if self.obj == temp_family.get_mother_handle():
|
||||
if temp_family.get_father_handle() is not None:
|
||||
error = True
|
||||
else:
|
||||
temp_family.set_mother_handle(None)
|
||||
temp_family.set_father_handle(self.obj)
|
||||
|
||||
if error:
|
||||
msg2 = _("Problem changing the gender")
|
||||
msg = _("Changing the gender caused problems "
|
||||
"with marriage information.\nPlease check "
|
||||
"the person's marriages.")
|
||||
ErrorDialog(msg2, msg)
|
||||
|
||||
def save(self, *obj):
|
||||
"""
|
||||
Save the data.
|
||||
"""
|
||||
self.ok_button.set_sensitive(False)
|
||||
if self.object_is_empty():
|
||||
ErrorDialog(_("Cannot save person"),
|
||||
_("No data exists for this person. Please "
|
||||
"enter data or cancel the edit."))
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
(uses_dupe_id, id) = self._uses_duplicate_id()
|
||||
if uses_dupe_id:
|
||||
prim_object = self.get_from_gramps_id(id)
|
||||
name = self.name_displayer.display(prim_object)
|
||||
msg1 = _("Cannot save person. ID already exists.")
|
||||
msg2 = _("You have attempted to use the existing Gramps ID with "
|
||||
"value %(id)s. This value is already used by '"
|
||||
"%(prim_object)s'. Please enter a different ID or leave "
|
||||
"blank to get the next available ID value.") % {
|
||||
'id' : id, 'prim_object' : name }
|
||||
ErrorDialog(msg1, msg2)
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
self._check_for_unknown_gender()
|
||||
|
||||
set_birth_death_index(self.db, self.obj)
|
||||
|
||||
trans = self.db.transaction_begin()
|
||||
|
||||
|
||||
self._update_family_ids()
|
||||
|
||||
if not self.obj.get_handle():
|
||||
self.db.add_person(self.obj, trans)
|
||||
msg = _("Add Person (%s)") % self.name_displayer.display(self.obj)
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_person_gramps_id())
|
||||
self.db.commit_person(self.obj, trans)
|
||||
msg = _("Edit Person (%s)") % self.name_displayer.display(self.obj)
|
||||
|
||||
self.db.transaction_commit(trans, msg)
|
||||
self.close()
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
|
||||
def _edit_name_clicked(self, obj):
|
||||
"""
|
||||
Bring up the EditName dialog for this name.
|
||||
|
||||
Called when the edit name button is clicked for the primary name
|
||||
on the main form (not in the names tab).
|
||||
|
||||
"""
|
||||
EditName(self.dbstate, self.uistate, self.track,
|
||||
self.pname, self._update_name)
|
||||
|
||||
def _update_name(self, name):
|
||||
"""
|
||||
Called when the primary name has been changed by the EditName
|
||||
dialog.
|
||||
|
||||
This allows us to update the main form in response to any changes.
|
||||
|
||||
"""
|
||||
for obj in (self.prefix_suffix, self.patro_title, self.given,
|
||||
self.ntype_field, self.surname_field, self.call):
|
||||
obj.update()
|
||||
|
||||
def load_person_image(self):
|
||||
"""
|
||||
Load the primary image into the main form if it exists.
|
||||
|
||||
Used as callback on Gallery Tab too.
|
||||
|
||||
"""
|
||||
media_list = self.obj.get_media_list()
|
||||
if media_list:
|
||||
photo = media_list[0]
|
||||
object_handle = photo.get_reference_handle()
|
||||
obj = self.db.get_object_from_handle(object_handle)
|
||||
full_path = Utils.media_path_full(self.dbstate.db, obj.get_path())
|
||||
#reload if different media, or different rectangle
|
||||
if self.load_obj != full_path or \
|
||||
self.load_rect != photo.get_rectangle():
|
||||
mime_type = obj.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
self.load_photo(full_path, photo.get_rectangle())
|
||||
else:
|
||||
self.load_photo(None)
|
||||
else:
|
||||
self.load_photo(None)
|
||||
|
||||
def birth_dates_in_order(self, child_ref_list):
|
||||
"""
|
||||
Check any *valid* birthdates in the list to insure that they are in
|
||||
numerically increasing order.
|
||||
"""
|
||||
inorder = True
|
||||
prev_date = 0
|
||||
handle_list = [ref.ref for ref in child_ref_list]
|
||||
for i in range(len(handle_list)):
|
||||
child_handle = handle_list[i]
|
||||
child = self.db.get_person_from_handle(child_handle)
|
||||
if child.get_birth_ref():
|
||||
event_handle = child.get_birth_ref().ref
|
||||
event = self.db.get_event_from_handle(event_handle)
|
||||
child_date = event.get_date_object().get_sort_value()
|
||||
else:
|
||||
continue
|
||||
if (prev_date <= child_date): # <= allows for twins
|
||||
prev_date = child_date
|
||||
else:
|
||||
inorder = False
|
||||
return inorder
|
||||
|
||||
def reorder_child_ref_list(self, person, child_ref_list):
|
||||
"""
|
||||
Reorder the child list to put the specified person in his/her
|
||||
correct birth order.
|
||||
|
||||
Only check *valid* birthdates. Move the person as short a distance as
|
||||
possible.
|
||||
|
||||
"""
|
||||
|
||||
if self.birth_dates_in_order(child_ref_list):
|
||||
return(child_ref_list)
|
||||
|
||||
# Build the person's date string once
|
||||
event_ref = person.get_birth_ref()
|
||||
if event_ref:
|
||||
event = self.db.get_event_from_handle(event_ref.ref)
|
||||
person_bday = event.get_date_object().get_sort_value()
|
||||
else:
|
||||
person_bday = 0
|
||||
|
||||
# First, see if the person needs to be moved forward in the list
|
||||
handle_list = [ref.ref for ref in child_ref_list]
|
||||
|
||||
index = handle_list.index(person.get_handle())
|
||||
target = index
|
||||
for i in range(index-1, -1, -1):
|
||||
other = self.db.get_person_from_handle(handle_list[i])
|
||||
event_ref = other.get_birth_ref()
|
||||
if event_ref:
|
||||
event = self.db.get_event_from_handle(event_ref.ref)
|
||||
other_bday = event.get_date_object().get_sort_value()
|
||||
if other_bday == 0:
|
||||
continue
|
||||
if person_bday < other_bday:
|
||||
target = i
|
||||
else:
|
||||
continue
|
||||
|
||||
# Now try moving to a later position in the list
|
||||
if (target == index):
|
||||
for i in range(index, len(handle_list)):
|
||||
other = self.db.get_person_from_handle(handle_list[i])
|
||||
event_ref = other.get_birth_ref()
|
||||
if event_ref:
|
||||
event = self.db.get_event_from_handle(event_ref.ref)
|
||||
other_bday = event.get_date_object().get_sort_value()
|
||||
if other_bday == "99999999":
|
||||
continue
|
||||
if person_bday > other_bday:
|
||||
target = i
|
||||
else:
|
||||
continue
|
||||
|
||||
# Actually need to move? Do it now.
|
||||
if (target != index):
|
||||
ref = child_ref_list.pop(index)
|
||||
child_ref_list.insert(target, ref)
|
||||
return child_ref_list
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
config.set('interface.prefix-suffix', self.prefix_suffix.active_key)
|
||||
config.set('interface.patro-title', self.patro_title.active_key)
|
||||
config.save()
|
||||
|
||||
|
||||
class GenderDialog(gtk.MessageDialog):
|
||||
def __init__(self, parent=None):
|
||||
gtk.MessageDialog.__init__(self,
|
||||
parent,
|
||||
flags=gtk.DIALOG_MODAL,
|
||||
type=gtk.MESSAGE_QUESTION,
|
||||
)
|
||||
self.set_icon(ICON)
|
||||
self.set_title('')
|
||||
|
||||
self.set_markup('<span size="larger" weight="bold">%s</span>' %
|
||||
_('Unknown gender specified'))
|
||||
self.format_secondary_text(
|
||||
_("The gender of the person is currently unknown. "
|
||||
"Usually, this is a mistake. Please specify the gender."))
|
||||
|
||||
self.add_button(_('_Male'), gen.lib.Person.MALE)
|
||||
self.add_button(_('_Female'), gen.lib.Person.FEMALE)
|
||||
self.add_button(_('_Unknown'), gen.lib.Person.UNKNOWN)
|
||||
177
src/gui/editors/editpersonref.py
Normal file
177
src/gui/editors/editpersonref.py
Normal file
@@ -0,0 +1,177 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
"""
|
||||
The EditPersonRef module provides the EditPersonRef class. This provides a
|
||||
mechanism for the user to edit address information.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from BasicUtils import name_displayer
|
||||
from editsecondary import EditSecondary
|
||||
from gen.lib import NoteType
|
||||
from gui.widgets import MonitoredEntry, PrivacyButton
|
||||
from gui.selectors import SelectorFactory
|
||||
from DisplayTabs import SourceEmbedList, NoteTab
|
||||
from glade import Glade
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditPersonRef class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditPersonRef(EditSecondary):
|
||||
"""
|
||||
Displays a dialog that allows the user to edit an address.
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate, uistate, track, addr, callback):
|
||||
"""
|
||||
Displays the dialog box.
|
||||
|
||||
parent - The class that called the PersonRef editor.
|
||||
addr - The address that is to be edited
|
||||
"""
|
||||
EditSecondary.__init__(self, dbstate, uistate, track, addr, callback)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.person-ref-width'
|
||||
self.height_key = 'interface.person-ref-height'
|
||||
|
||||
self.top = Glade()
|
||||
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object("title"),
|
||||
_('Person Reference Editor'))
|
||||
self.person_label = self.top.get_object('person')
|
||||
|
||||
def _setup_fields(self):
|
||||
|
||||
if self.obj.ref:
|
||||
p = self.dbstate.db.get_person_from_handle(self.obj.ref)
|
||||
self.person_label.set_text(name_displayer.display(p))
|
||||
|
||||
self.street = MonitoredEntry(
|
||||
self.top.get_object("relationship"),
|
||||
self.obj.set_relation,
|
||||
self.obj.get_relation,
|
||||
self.db.readonly)
|
||||
|
||||
self.priv = PrivacyButton(
|
||||
self.top.get_object("private"),
|
||||
self.obj,
|
||||
self.db.readonly)
|
||||
|
||||
def _connect_signals(self):
|
||||
#self.define_help_button(self.top.get_object('help'))
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
self.define_ok_button(self.top.get_object('ok'),self.save)
|
||||
self.top.get_object('select').connect('clicked',self._select_person)
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('person-rebuild', self.close)
|
||||
self._add_db_signal('person-delete', self.check_for_close)
|
||||
|
||||
def check_for_close(self, handles):
|
||||
"""
|
||||
Callback method for delete signals.
|
||||
If there is a delete signal of the primary object we are editing, the
|
||||
editor (and all child windows spawned) should be closed
|
||||
"""
|
||||
if self.obj.ref in handles:
|
||||
self.close()
|
||||
|
||||
def _select_person(self, obj):
|
||||
SelectPerson = SelectorFactory('Person')
|
||||
|
||||
sel = SelectPerson(self.dbstate, self.uistate, self.track)
|
||||
person = sel.run()
|
||||
|
||||
if person:
|
||||
self.obj.ref = person.get_handle()
|
||||
self.person_label.set_text(name_displayer.display(person))
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
Create the notebook tabs and inserts them into the main
|
||||
window.
|
||||
"""
|
||||
|
||||
notebook = gtk.Notebook()
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=NoteType.ASSOCIATION))
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
notebook.show_all()
|
||||
self.top.get_object('vbox').pack_start(notebook,True)
|
||||
|
||||
def build_menu_names(self, obj):
|
||||
return (_('Person Reference'),_('Person Reference Editor'))
|
||||
|
||||
def save(self,*obj):
|
||||
"""
|
||||
Called when the OK button is pressed. Gets data from the
|
||||
form and updates the Address data structure.
|
||||
"""
|
||||
|
||||
if self.obj.ref:
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
else:
|
||||
from QuestionDialog import ErrorDialog
|
||||
|
||||
ErrorDialog(
|
||||
_('No person selected'),
|
||||
_('You must either select a person or Cancel '
|
||||
'the edit'))
|
||||
362
src/gui/editors/editplace.py
Normal file
362
src/gui/editors/editplace.py
Normal file
@@ -0,0 +1,362 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# Copyright (C) 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
import logging
|
||||
log = logging.getLogger(".")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gen.lib
|
||||
from editprimary import EditPrimary
|
||||
from DisplayTabs import (GrampsTab, LocationEmbedList, SourceEmbedList,
|
||||
GalleryTab, NoteTab, WebEmbedList, PlaceBackRefList)
|
||||
from gui.widgets import MonitoredEntry, PrivacyButton
|
||||
from Errors import ValidationError
|
||||
from PlaceUtils import conv_lat_lon
|
||||
from QuestionDialog import ErrorDialog
|
||||
from glade import Glade
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class MainLocTab(GrampsTab):
|
||||
"""
|
||||
This class provides the tabpage of the main location tab
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate, uistate, track, name, widget):
|
||||
"""
|
||||
@param dbstate: The database state. Contains a reference to
|
||||
the database, along with other state information. The GrampsTab
|
||||
uses this to access the database and to pass to and created
|
||||
child windows (such as edit dialogs).
|
||||
@type dbstate: DbState
|
||||
@param uistate: The UI state. Used primarily to pass to any created
|
||||
subwindows.
|
||||
@type uistate: DisplayState
|
||||
@param track: The window tracking mechanism used to manage windows.
|
||||
This is only used to pass to generted child windows.
|
||||
@type track: list
|
||||
@param name: Notebook label name
|
||||
@type name: str/unicode
|
||||
@param widget: widget to be shown in the tab
|
||||
@type widge: gtk widget
|
||||
"""
|
||||
GrampsTab.__init__(self, dbstate, uistate, track, name)
|
||||
eventbox = gtk.EventBox()
|
||||
eventbox.add(widget)
|
||||
self.pack_start(eventbox)
|
||||
self._set_label(show_image=False)
|
||||
eventbox.connect('key_press_event', self.key_pressed)
|
||||
self.show_all()
|
||||
|
||||
def is_empty(self):
|
||||
"""
|
||||
Override base class
|
||||
"""
|
||||
return False
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditPlace
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditPlace(EditPrimary):
|
||||
|
||||
def __init__(self, dbstate, uistate, track, place, callback=None):
|
||||
EditPrimary.__init__(self, dbstate, uistate, track, place,
|
||||
dbstate.db.get_place_from_handle,
|
||||
dbstate.db.get_place_from_gramps_id, callback)
|
||||
|
||||
def empty_object(self):
|
||||
return gen.lib.Place()
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.place-width'
|
||||
self.height_key = 'interface.place-height'
|
||||
|
||||
self.top = Glade()
|
||||
|
||||
self.set_window(self.top.toplevel, None,
|
||||
self.get_menu_title())
|
||||
tblmloc = self.top.get_object('table19')
|
||||
notebook = self.top.get_object('notebook3')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.mloc = MainLocTab(self.dbstate, self.uistate, self.track,
|
||||
_('_Location'), tblmloc)
|
||||
self.track_ref_for_deletion("mloc")
|
||||
|
||||
|
||||
def get_menu_title(self):
|
||||
if self.obj and self.obj.get_handle():
|
||||
title = self.obj.get_title()
|
||||
dialog_title = _('Place: %s') % title
|
||||
else:
|
||||
dialog_title = _('New Place')
|
||||
return dialog_title
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_ok_button(self.top.get_object('ok'), self.save)
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
self.define_help_button(self.top.get_object('help'))
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('place-rebuild', self._do_close)
|
||||
self._add_db_signal('place-delete', self.check_for_close)
|
||||
|
||||
def _setup_fields(self):
|
||||
mloc = self.obj.get_main_location()
|
||||
|
||||
self.title = MonitoredEntry(self.top.get_object("place_title"),
|
||||
self.obj.set_title, self.obj.get_title,
|
||||
self.db.readonly)
|
||||
|
||||
self.street = MonitoredEntry(self.top.get_object("street"),
|
||||
mloc.set_street, mloc.get_street,
|
||||
self.db.readonly)
|
||||
|
||||
self.city = MonitoredEntry(self.top.get_object("city"),
|
||||
mloc.set_city, mloc.get_city,
|
||||
self.db.readonly)
|
||||
|
||||
self.gid = MonitoredEntry(self.top.get_object("gid"),
|
||||
self.obj.set_gramps_id,
|
||||
self.obj.get_gramps_id, self.db.readonly)
|
||||
|
||||
self.privacy = PrivacyButton(self.top.get_object("private"), self.obj,
|
||||
self.db.readonly)
|
||||
|
||||
self.parish = MonitoredEntry(self.top.get_object("parish"),
|
||||
mloc.set_parish, mloc.get_parish,
|
||||
self.db.readonly)
|
||||
|
||||
self.county = MonitoredEntry(self.top.get_object("county"),
|
||||
mloc.set_county, mloc.get_county,
|
||||
self.db.readonly)
|
||||
|
||||
self.state = MonitoredEntry(self.top.get_object("state"),
|
||||
mloc.set_state, mloc.get_state,
|
||||
self.db.readonly)
|
||||
|
||||
self.phone = MonitoredEntry(self.top.get_object("phone"),
|
||||
mloc.set_phone, mloc.get_phone,
|
||||
self.db.readonly)
|
||||
|
||||
self.postal = MonitoredEntry(self.top.get_object("postal"),
|
||||
mloc.set_postal_code,
|
||||
mloc.get_postal_code, self.db.readonly)
|
||||
|
||||
self.country = MonitoredEntry(self.top.get_object("country"),
|
||||
mloc.set_country, mloc.get_country,
|
||||
self.db.readonly)
|
||||
|
||||
self.longitude = MonitoredEntry(
|
||||
self.top.get_object("lon_entry"),
|
||||
self.obj.set_longitude, self.obj.get_longitude,
|
||||
self.db.readonly)
|
||||
self.longitude.connect("validate", self._validate_coordinate, "lon")
|
||||
#force validation now with initial entry
|
||||
self.top.get_object("lon_entry").validate(force=True)
|
||||
|
||||
self.latitude = MonitoredEntry(
|
||||
self.top.get_object("lat_entry"),
|
||||
self.obj.set_latitude, self.obj.get_latitude,
|
||||
self.db.readonly)
|
||||
self.latitude.connect("validate", self._validate_coordinate, "lat")
|
||||
#force validation now with initial entry
|
||||
self.top.get_object("lat_entry").validate(force=True)
|
||||
|
||||
def _validate_coordinate(self, widget, text, typedeg):
|
||||
if (typedeg == 'lat') and not conv_lat_lon(text, "0", "ISO-D"):
|
||||
return ValidationError(_(u"Invalid latitude (syntax: 18\u00b09'") +
|
||||
_('48.21"S, -18.2412 or -18:9:48.21)'))
|
||||
elif (typedeg == 'lon') and not conv_lat_lon("0", text, "ISO-D"):
|
||||
return ValidationError(_(u"Invalid longitude (syntax: 18\u00b09'") +
|
||||
_('48.21"E, -18.2412 or -18:9:48.21)'))
|
||||
|
||||
def build_menu_names(self, place):
|
||||
return (_('Edit Place'), self.get_menu_title())
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
Create the notebook tabs and inserts them into the main
|
||||
window.
|
||||
|
||||
"""
|
||||
notebook = self.top.get_object('notebook3')
|
||||
|
||||
self._add_tab(notebook, self.mloc)
|
||||
|
||||
self.loc_list = LocationEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.alt_loc)
|
||||
self._add_tab(notebook, self.loc_list)
|
||||
self.track_ref_for_deletion("loc_list")
|
||||
|
||||
self.srcref_list = SourceEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj)
|
||||
self._add_tab(notebook, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.note_tab = NoteTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_note_list(),
|
||||
self.get_menu_title(),
|
||||
notetype=gen.lib.NoteType.PLACE)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self.gallery_tab = GalleryTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_media_list())
|
||||
self._add_tab(notebook, self.gallery_tab)
|
||||
self.track_ref_for_deletion("gallery_tab")
|
||||
|
||||
self.web_list = WebEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_url_list())
|
||||
self._add_tab(notebook, self.web_list)
|
||||
self.track_ref_for_deletion("web_list")
|
||||
|
||||
self.backref_list = PlaceBackRefList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.find_backlink_handles(self.obj.handle))
|
||||
self.backref_tab = self._add_tab(notebook, self.backref_list)
|
||||
self.track_ref_for_deletion("backref_list")
|
||||
self.track_ref_for_deletion("backref_tab")
|
||||
|
||||
self._setup_notebook_tabs(notebook)
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
self.backref_tab.close()
|
||||
|
||||
def save(self, *obj):
|
||||
self.ok_button.set_sensitive(False)
|
||||
if self.object_is_empty():
|
||||
ErrorDialog(_("Cannot save place"),
|
||||
_("No data exists for this place. Please "
|
||||
"enter data or cancel the edit."))
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
(uses_dupe_id, id) = self._uses_duplicate_id()
|
||||
if uses_dupe_id:
|
||||
prim_object = self.get_from_gramps_id(id)
|
||||
name = prim_object.get_title()
|
||||
msg1 = _("Cannot save place. ID already exists.")
|
||||
msg2 = _("You have attempted to use the existing Gramps ID with "
|
||||
"value %(id)s. This value is already used by '"
|
||||
"%(prim_object)s'. Please enter a different ID or leave "
|
||||
"blank to get the next available ID value.") % {
|
||||
'id' : id, 'prim_object' : name }
|
||||
ErrorDialog(msg1, msg2)
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
trans = self.db.transaction_begin()
|
||||
if not self.obj.get_handle():
|
||||
self.db.add_place(self.obj, trans)
|
||||
msg = _("Add Place (%s)") % self.obj.get_title()
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_place_gramps_id())
|
||||
self.db.commit_place(self.obj, trans)
|
||||
msg = _("Edit Place (%s)") % self.obj.get_title()
|
||||
self.db.transaction_commit(trans, msg)
|
||||
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# DeletePlaceQuery
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class DeletePlaceQuery(object):
|
||||
|
||||
def __init__(self, dbstate, uistate, place, person_list, family_list,
|
||||
event_list):
|
||||
self.db = dbstate.db
|
||||
self.uistate = uistate
|
||||
self.obj = place
|
||||
self.person_list = person_list
|
||||
self.family_list = family_list
|
||||
self.event_list = event_list
|
||||
|
||||
def query_response(self):
|
||||
trans = self.db.transaction_begin()
|
||||
self.db.disable_signals()
|
||||
|
||||
place_handle = self.obj.get_handle()
|
||||
|
||||
for handle in self.person_list:
|
||||
person = self.db.get_person_from_handle(handle)
|
||||
person.remove_handle_references('Place', place_handle)
|
||||
self.db.commit_person(person, trans)
|
||||
|
||||
for handle in self.family_list:
|
||||
family = self.db.get_family_from_handle(handle)
|
||||
family.remove_handle_references('Place', place_handle)
|
||||
self.db.commit_family(family, trans)
|
||||
|
||||
for handle in self.event_list:
|
||||
event = self.db.get_event_from_handle(handle)
|
||||
event.remove_handle_references('Place', place_handle)
|
||||
self.db.commit_event(event, trans)
|
||||
|
||||
self.db.enable_signals()
|
||||
self.db.remove_place(place_handle, trans)
|
||||
self.db.transaction_commit(
|
||||
trans,_("Delete Place (%s)") % self.obj.get_title())
|
||||
327
src/gui/editors/editprimary.py
Normal file
327
src/gui/editors/editprimary.py
Normal file
@@ -0,0 +1,327 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import ManagedWindow
|
||||
import DateHandler
|
||||
from BasicUtils import name_displayer
|
||||
import config
|
||||
import GrampsDisplay
|
||||
from QuestionDialog import SaveDialog
|
||||
import gen.lib
|
||||
from gui.dbguielement import DbGUIElement
|
||||
|
||||
class EditPrimary(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
|
||||
QR_CATEGORY = -1
|
||||
|
||||
def __init__(self, state, uistate, track, obj, get_from_handle,
|
||||
get_from_gramps_id, callback=None):
|
||||
"""
|
||||
Create an edit window.
|
||||
|
||||
Associate a person with the window.
|
||||
|
||||
"""
|
||||
self.dp = DateHandler.parser
|
||||
self.dd = DateHandler.displayer
|
||||
self.name_displayer = name_displayer
|
||||
self.obj = obj
|
||||
self.dbstate = state
|
||||
self.uistate = uistate
|
||||
self.db = state.db
|
||||
self.callback = callback
|
||||
self.ok_button = None
|
||||
self.get_from_handle = get_from_handle
|
||||
self.get_from_gramps_id = get_from_gramps_id
|
||||
self.contexteventbox = None
|
||||
self.__tabs = []
|
||||
|
||||
ManagedWindow.ManagedWindow.__init__(self, uistate, track, obj)
|
||||
DbGUIElement.__init__(self, self.db)
|
||||
|
||||
self._local_init()
|
||||
self._set_size()
|
||||
self._create_tabbed_pages()
|
||||
self._setup_fields()
|
||||
self._connect_signals()
|
||||
#if the database is changed, all info shown is invalid and the window
|
||||
# should close
|
||||
self.dbstate.connect('database-changed', self._do_close)
|
||||
self.show()
|
||||
self._post_init()
|
||||
|
||||
def _local_init(self):
|
||||
"""
|
||||
Derived class should do any pre-window initalization in this task.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _post_init(self):
|
||||
"""
|
||||
Derived class should do any post-window initalization in this task.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _setup_fields(self):
|
||||
pass
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
pass
|
||||
|
||||
def _connect_signals(self):
|
||||
pass
|
||||
|
||||
def build_window_key(self, obj):
|
||||
if obj and obj.get_handle():
|
||||
return obj.get_handle()
|
||||
else:
|
||||
return id(self)
|
||||
|
||||
def _setup_notebook_tabs(self, notebook):
|
||||
for child in notebook.get_children():
|
||||
label = notebook.get_tab_label(child)
|
||||
page_no = notebook.page_num(child)
|
||||
label.drag_dest_set(0, [], 0)
|
||||
label.connect('drag_motion',
|
||||
self._switch_page_on_dnd,
|
||||
notebook,
|
||||
page_no)
|
||||
child.set_parent_notebook(notebook)
|
||||
|
||||
notebook.connect('key-press-event', self.key_pressed, notebook)
|
||||
|
||||
def key_pressed(self, obj, event, notebook):
|
||||
"""
|
||||
Handles the key being pressed on the notebook, pass to key press of
|
||||
current page.
|
||||
"""
|
||||
pag = notebook.get_current_page()
|
||||
if not pag == -1:
|
||||
notebook.get_nth_page(pag).key_pressed(obj, event)
|
||||
|
||||
def _switch_page_on_dnd(self, widget, context, x, y, time, notebook,
|
||||
page_no):
|
||||
if notebook.get_current_page() != page_no:
|
||||
notebook.set_current_page(page_no)
|
||||
|
||||
def _add_tab(self, notebook, page):
|
||||
self.__tabs.append(page)
|
||||
notebook.insert_page(page, page.get_tab_widget())
|
||||
page.label.set_use_underline(True)
|
||||
return page
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
pass
|
||||
|
||||
def object_is_empty(self):
|
||||
return cmp(self.obj.serialize()[1:],
|
||||
self.empty_object().serialize()[1:]) == 0
|
||||
|
||||
def define_ok_button(self, button, function):
|
||||
self.ok_button = button
|
||||
button.connect('clicked', function)
|
||||
button.set_sensitive(not self.db.readonly)
|
||||
|
||||
def define_cancel_button(self, button):
|
||||
button.connect('clicked', self.close)
|
||||
|
||||
def define_help_button(self, button, webpage='', section=''):
|
||||
button.connect('clicked', lambda x: GrampsDisplay.help(webpage,
|
||||
section))
|
||||
|
||||
def _do_close(self, *obj):
|
||||
self._cleanup_db_connects()
|
||||
self._cleanup_on_exit()
|
||||
ManagedWindow.ManagedWindow.close(self)
|
||||
|
||||
def _cleanup_db_connects(self):
|
||||
"""
|
||||
All connects that happened to signals of the db must be removed on
|
||||
closed. This implies two things:
|
||||
1. The connects on the main view must be disconnected
|
||||
2. Connects done in subelements must be disconnected
|
||||
"""
|
||||
#cleanup callbackmanager of this editor
|
||||
self._cleanup_callbacks()
|
||||
for tab in [tab for tab in self.__tabs if hasattr(tab, 'callman')]:
|
||||
tab._cleanup_callbacks()
|
||||
|
||||
def check_for_close(self, handles):
|
||||
"""
|
||||
Callback method for delete signals.
|
||||
If there is a delete signal of the primary object we are editing, the
|
||||
editor (and all child windows spawned) should be closed
|
||||
"""
|
||||
if self.obj.get_handle() in handles:
|
||||
self._do_close()
|
||||
|
||||
def close(self, *obj):
|
||||
"""If the data has changed, give the user a chance to cancel
|
||||
the close window"""
|
||||
if not config.get('interface.dont-ask') and self.data_has_changed():
|
||||
SaveDialog(
|
||||
_('Save Changes?'),
|
||||
_('If you close without saving, the changes you '
|
||||
'have made will be lost'),
|
||||
self._do_close,
|
||||
self.save)
|
||||
return True
|
||||
else:
|
||||
self._do_close()
|
||||
return False
|
||||
|
||||
def empty_object(self):
|
||||
#empty_object should be overridden in base class and will throw an
|
||||
#exception if it is not because self.empty_object().serialize() is
|
||||
#called and PrimaryObject does not implement serialize(). See
|
||||
#BaseObject.serialize()
|
||||
return gen.lib.PrimaryObject
|
||||
|
||||
def data_has_changed(self):
|
||||
|
||||
if self.db.readonly:
|
||||
return False
|
||||
elif self.obj.handle:
|
||||
orig = self.get_from_handle(self.obj.handle)
|
||||
if orig:
|
||||
cmp_obj = orig
|
||||
else:
|
||||
cmp_obj = self.empty_object()
|
||||
return cmp(cmp_obj.serialize()[1:],
|
||||
self.obj.serialize()[1:]) != 0
|
||||
else:
|
||||
cmp_obj = self.empty_object()
|
||||
return cmp(cmp_obj.serialize()[1:],
|
||||
self.obj.serialize()[1:]) != 0
|
||||
|
||||
def save(self, *obj):
|
||||
pass
|
||||
|
||||
def set_contexteventbox(self, eventbox):
|
||||
"""Set the contextbox that grabs button presses if not grabbed
|
||||
by overlying widgets.
|
||||
"""
|
||||
self.contexteventbox = eventbox
|
||||
self.contexteventbox.connect('button-press-event',
|
||||
self._contextmenu_button_press)
|
||||
|
||||
def _contextmenu_button_press(self, obj, event) :
|
||||
"""
|
||||
Button press event that is caught when a mousebutton has been
|
||||
pressed while on contexteventbox
|
||||
It opens a context menu with possible actions
|
||||
"""
|
||||
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3 :
|
||||
if self.obj.get_handle() == 0 :
|
||||
return False
|
||||
|
||||
#build the possible popup menu
|
||||
self._build_popup_ui()
|
||||
#set or unset sensitivity in popup
|
||||
self._post_build_popup_ui()
|
||||
|
||||
menu = self.popupmanager.get_widget('/Popup')
|
||||
if menu:
|
||||
menu.popup(None, None, None, event.button, event.time)
|
||||
return True
|
||||
return False
|
||||
|
||||
def _build_popup_ui(self):
|
||||
"""
|
||||
Create actions and ui of context menu
|
||||
"""
|
||||
from QuickReports import create_quickreport_menu
|
||||
|
||||
self.popupmanager = gtk.UIManager()
|
||||
#add custom actions
|
||||
(ui_top, action_groups) = self._top_contextmenu()
|
||||
for action in action_groups :
|
||||
self.popupmanager.insert_action_group(action, -1)
|
||||
#see which quick reports are available now:
|
||||
ui_qr = ''
|
||||
if self.QR_CATEGORY > -1 :
|
||||
(ui_qr, reportactions) = create_quickreport_menu(self.QR_CATEGORY,
|
||||
self.dbstate, self.uistate,
|
||||
self.obj.get_handle())
|
||||
self.report_action = gtk.ActionGroup("/PersonReport")
|
||||
self.report_action.add_actions(reportactions)
|
||||
self.report_action.set_visible(True)
|
||||
self.popupmanager.insert_action_group(self.report_action, -1)
|
||||
|
||||
popupui = '''
|
||||
<ui>
|
||||
<popup name="Popup">''' + ui_top + '''
|
||||
<separator/>''' + ui_qr + '''
|
||||
</popup>
|
||||
</ui>'''
|
||||
|
||||
self.popupmanager.add_ui_from_string(popupui)
|
||||
|
||||
def _top_contextmenu(self):
|
||||
"""
|
||||
Derived class can create a ui with menuitems and corresponding list of
|
||||
actiongroups
|
||||
"""
|
||||
return "", []
|
||||
|
||||
def _post_build_popup_ui(self):
|
||||
"""
|
||||
Derived class should do extra actions here on the menu
|
||||
"""
|
||||
pass
|
||||
|
||||
def _uses_duplicate_id(self):
|
||||
"""
|
||||
Check whether a changed or added GRAMPS ID already exists in the DB.
|
||||
|
||||
Return True if a duplicate GRAMPS ID has been detected.
|
||||
|
||||
"""
|
||||
original = self.get_from_handle(self.obj.get_handle())
|
||||
if original and original.get_gramps_id() == self.obj.get_gramps_id():
|
||||
return (False, 0)
|
||||
else:
|
||||
idval = self.obj.get_gramps_id()
|
||||
if self.get_from_gramps_id(idval):
|
||||
return (True, idval)
|
||||
return (False, 0)
|
||||
|
||||
224
src/gui/editors/editreference.py
Normal file
224
src/gui/editors/editreference.py
Normal file
@@ -0,0 +1,224 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import ManagedWindow
|
||||
from DisplayTabs import GrampsTab
|
||||
import config
|
||||
from gui.dbguielement import DbGUIElement
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class RefTab(GrampsTab):
|
||||
"""
|
||||
This class provides a simple tabpage for use on EditReference
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate, uistate, track, name, widget):
|
||||
"""
|
||||
@param dbstate: The database state. Contains a reference to
|
||||
the database, along with other state information. The GrampsTab
|
||||
uses this to access the database and to pass to and created
|
||||
child windows (such as edit dialogs).
|
||||
@type dbstate: DbState
|
||||
@param uistate: The UI state. Used primarily to pass to any created
|
||||
subwindows.
|
||||
@type uistate: DisplayState
|
||||
@param track: The window tracking mechanism used to manage windows.
|
||||
This is only used to pass to generted child windows.
|
||||
@type track: list
|
||||
@param name: Notebook label name
|
||||
@type name: str/unicode
|
||||
@param widget: widget to be shown in the tab
|
||||
@type widge: gtk widget
|
||||
"""
|
||||
GrampsTab.__init__(self, dbstate, uistate, track, name)
|
||||
eventbox = gtk.EventBox()
|
||||
eventbox.add(widget)
|
||||
self.pack_start(eventbox)
|
||||
self._set_label(show_image=False)
|
||||
widget.connect('key_press_event', self.key_pressed)
|
||||
self.show_all()
|
||||
|
||||
def is_empty(self):
|
||||
"""
|
||||
Override base class
|
||||
"""
|
||||
return False
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditReference class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditReference(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
|
||||
def __init__(self, state, uistate, track, source, source_ref, update):
|
||||
self.db = state.db
|
||||
self.dbstate = state
|
||||
self.uistate = uistate
|
||||
self.source_ref = source_ref
|
||||
self.source = source
|
||||
self.source_added = False
|
||||
self.update = update
|
||||
self.warn_box = None
|
||||
self.__tabs = []
|
||||
|
||||
ManagedWindow.ManagedWindow.__init__(self, uistate, track, source_ref)
|
||||
DbGUIElement.__init__(self, self.db)
|
||||
|
||||
self._local_init()
|
||||
self._set_size()
|
||||
self._create_tabbed_pages()
|
||||
self._setup_fields()
|
||||
self._connect_signals()
|
||||
self.show()
|
||||
self._post_init()
|
||||
|
||||
def _local_init(self):
|
||||
"""
|
||||
Derived class should do any pre-window initalization in this task.
|
||||
"""
|
||||
pass
|
||||
|
||||
def define_warn_box(self,box):
|
||||
self.warn_box = box
|
||||
|
||||
def enable_warnbox(self):
|
||||
self.warn_box.show()
|
||||
|
||||
def define_expander(self,expander):
|
||||
expander.set_expanded(True)
|
||||
|
||||
def _post_init(self):
|
||||
"""
|
||||
Derived class should do any post-window initalization in this task.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _setup_notebook_tabs(self, notebook):
|
||||
for child in notebook.get_children():
|
||||
label = notebook.get_tab_label(child)
|
||||
page_no = notebook.page_num(child)
|
||||
label.drag_dest_set(0, [], 0)
|
||||
label.connect('drag_motion',
|
||||
self._switch_page_on_dnd,
|
||||
notebook,
|
||||
page_no)
|
||||
child.set_parent_notebook(notebook)
|
||||
notebook.connect('key-press-event', self.key_pressed, notebook)
|
||||
|
||||
def key_pressed(self, obj, event, notebook):
|
||||
"""
|
||||
Handles the key being pressed on the notebook, pass to key press of
|
||||
current page.
|
||||
"""
|
||||
pag = notebook.get_current_page()
|
||||
if not pag == -1:
|
||||
notebook.get_nth_page(pag).key_pressed(obj, event)
|
||||
|
||||
def _switch_page_on_dnd(self, widget, context, x, y, time, notebook, page_no):
|
||||
if notebook.get_current_page() != page_no:
|
||||
notebook.set_current_page(page_no)
|
||||
|
||||
def _add_tab(self, notebook,page):
|
||||
self.__tabs.append(page)
|
||||
notebook.insert_page(page, page.get_tab_widget())
|
||||
page.label.set_use_underline(True)
|
||||
return page
|
||||
|
||||
def _connect_signals(self):
|
||||
pass
|
||||
|
||||
def _setup_fields(self):
|
||||
pass
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
pass
|
||||
|
||||
def build_window_key(self,sourceref):
|
||||
#the window key for managedwindow identification. No need to return None
|
||||
if self.source and self.source.get_handle():
|
||||
return self.source.get_handle()
|
||||
else:
|
||||
return id(self)
|
||||
|
||||
def define_ok_button(self, button, function):
|
||||
button.connect('clicked',function)
|
||||
button.set_sensitive(not self.db.readonly)
|
||||
|
||||
def define_cancel_button(self, button):
|
||||
button.connect('clicked',self.close_and_cancel)
|
||||
|
||||
def close_and_cancel(self, obj):
|
||||
self._cleanup_on_exit()
|
||||
self.close(obj)
|
||||
|
||||
def check_for_close(self, handles):
|
||||
"""
|
||||
Callback method for delete signals.
|
||||
If there is a delete signal of the primary object we are editing, the
|
||||
editor (and all child windows spawned) should be closed
|
||||
"""
|
||||
if self.source.get_handle() in handles:
|
||||
self.close()
|
||||
|
||||
def define_help_button(self, button, webpage='', section=''):
|
||||
import GrampsDisplay
|
||||
button.connect('clicked', lambda x: GrampsDisplay.help(webpage,
|
||||
section))
|
||||
button.set_sensitive(True)
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
pass
|
||||
|
||||
def close(self,*obj):
|
||||
self._cleanup_db_connects()
|
||||
ManagedWindow.ManagedWindow.close(self)
|
||||
|
||||
def _cleanup_db_connects(self):
|
||||
"""
|
||||
All connects that happened to signals of the db must be removed on
|
||||
closed. This implies two things:
|
||||
1. The connects on the main view must be disconnected
|
||||
2. Connects done in subelements must be disconnected
|
||||
"""
|
||||
#cleanup callbackmanager of this editor
|
||||
self._cleanup_callbacks()
|
||||
for tab in [tab for tab in self.__tabs if hasattr(tab, 'callman')]:
|
||||
tab._cleanup_callbacks()
|
||||
202
src/gui/editors/editreporef.py
Normal file
202
src/gui/editors/editreporef.py
Normal file
@@ -0,0 +1,202 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gen.lib import NoteType
|
||||
|
||||
from DisplayTabs import NoteTab,AddrEmbedList,WebEmbedList,SourceBackRefList
|
||||
from gui.widgets import MonitoredEntry, PrivacyButton, MonitoredDataType
|
||||
from editreference import RefTab, EditReference
|
||||
from glade import Glade
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditRepoRef class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditRepoRef(EditReference):
|
||||
|
||||
def __init__(self, state, uistate, track, source, source_ref, update):
|
||||
|
||||
EditReference.__init__(self, state, uistate, track, source,
|
||||
source_ref, update)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.repo-ref-width'
|
||||
self.height_key = 'interface.repo-ref-height'
|
||||
|
||||
self.top = Glade()
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object('repo_title'),
|
||||
_('Repository Reference Editor'))
|
||||
|
||||
self.define_warn_box(self.top.get_object("warn_box"))
|
||||
self.define_expander(self.top.get_object("src_expander"))
|
||||
|
||||
tblref = self.top.get_object('table70')
|
||||
notebook = self.top.get_object('notebook_ref')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.reftab = RefTab(self.dbstate, self.uistate, self.track,
|
||||
_('General'), tblref)
|
||||
tblref = self.top.get_object('table69')
|
||||
notebook = self.top.get_object('notebook_src')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.primtab = RefTab(self.dbstate, self.uistate, self.track,
|
||||
_('_General'), tblref)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_ok_button(self.top.get_object('ok'),self.ok_clicked)
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('repository-rebuild', self.close)
|
||||
self._add_db_signal('repository-delete', self.check_for_close)
|
||||
|
||||
def _setup_fields(self):
|
||||
self.callno = MonitoredEntry(
|
||||
self.top.get_object("call_number"),
|
||||
self.source_ref.set_call_number,
|
||||
self.source_ref.get_call_number,
|
||||
self.db.readonly)
|
||||
|
||||
self.gid = MonitoredEntry(
|
||||
self.top.get_object('gid'),
|
||||
self.source.set_gramps_id,
|
||||
self.source.get_gramps_id,
|
||||
self.db.readonly)
|
||||
|
||||
self.privacy = PrivacyButton(
|
||||
self.top.get_object("private"),
|
||||
self.source,
|
||||
self.db.readonly)
|
||||
|
||||
self.privacy = PrivacyButton(
|
||||
self.top.get_object("private_ref"),
|
||||
self.source_ref,
|
||||
self.db.readonly)
|
||||
|
||||
self.title = MonitoredEntry(
|
||||
self.top.get_object('repo_name'),
|
||||
self.source.set_name,
|
||||
self.source.get_name,
|
||||
self.db.readonly)
|
||||
|
||||
self.type_selector = MonitoredDataType(
|
||||
self.top.get_object("media_type"),
|
||||
self.source_ref.set_media_type,
|
||||
self.source_ref.get_media_type,
|
||||
self.db.readonly,
|
||||
self.db.get_source_media_types(),
|
||||
)
|
||||
|
||||
self.media_type_selector = MonitoredDataType(
|
||||
self.top.get_object("repo_type"),
|
||||
self.source.set_type,
|
||||
self.source.get_type,
|
||||
self.db.readonly,
|
||||
self.db.get_repository_types(),
|
||||
)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
Create the notebook tabs and inserts them into the main
|
||||
window.
|
||||
"""
|
||||
|
||||
notebook_src = self.top.get_object('notebook_src')
|
||||
notebook_ref = self.top.get_object('notebook_ref')
|
||||
|
||||
self._add_tab(notebook_src, self.primtab)
|
||||
self._add_tab(notebook_ref, self.reftab)
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook_src,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_note_list(),
|
||||
notetype=NoteType.REPO))
|
||||
|
||||
self.comment_tab = self._add_tab(
|
||||
notebook_ref,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source_ref.get_note_list(),
|
||||
notetype=NoteType.REPOREF))
|
||||
|
||||
self.address_tab = self._add_tab(
|
||||
notebook_src,
|
||||
AddrEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source.get_address_list()))
|
||||
|
||||
self.web_list = self._add_tab(
|
||||
notebook_src,
|
||||
WebEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source.get_url_list()))
|
||||
|
||||
self.backref_tab = self._add_tab(
|
||||
notebook_src,
|
||||
SourceBackRefList(self.dbstate, self.uistate, self.track,
|
||||
self.db.find_backlink_handles(self.source.handle),
|
||||
self.enable_warnbox))
|
||||
|
||||
self._setup_notebook_tabs( notebook_src)
|
||||
self._setup_notebook_tabs( notebook_ref)
|
||||
|
||||
def build_menu_names(self,sourceref):
|
||||
if self.source:
|
||||
source_name = self.source.get_name()
|
||||
submenu_label = _('Repository: %s') % source_name
|
||||
else:
|
||||
submenu_label = _('New Repository')
|
||||
return (_('Repo Reference Editor'),submenu_label)
|
||||
|
||||
def ok_clicked(self, obj):
|
||||
|
||||
trans = self.db.transaction_begin()
|
||||
if self.source.handle:
|
||||
self.db.commit_repository(self.source,trans)
|
||||
self.db.transaction_commit(trans,_("Modify Repository"))
|
||||
else:
|
||||
self.db.add_repository(self.source,trans)
|
||||
self.db.transaction_commit(trans,_("Add Repository"))
|
||||
self.source_ref.ref = self.source.handle
|
||||
|
||||
if self.update:
|
||||
self.update((self.source_ref,self.source))
|
||||
|
||||
self.close()
|
||||
215
src/gui/editors/editrepository.py
Normal file
215
src/gui/editors/editrepository.py
Normal file
@@ -0,0 +1,215 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# Copyright (C) 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gen.lib
|
||||
|
||||
from gui.widgets import MonitoredEntry, MonitoredDataType, PrivacyButton
|
||||
from DisplayTabs import AddrEmbedList, WebEmbedList, NoteTab, SourceBackRefList
|
||||
from editprimary import EditPrimary
|
||||
from QuestionDialog import ErrorDialog
|
||||
from glade import Glade
|
||||
|
||||
class EditRepository(EditPrimary):
|
||||
|
||||
def __init__(self, dbstate, uistate, track, repository):
|
||||
|
||||
EditPrimary.__init__(self, dbstate, uistate, track, repository,
|
||||
dbstate.db.get_repository_from_handle,
|
||||
dbstate.db.get_repository_from_gramps_id)
|
||||
|
||||
def empty_object(self):
|
||||
return gen.lib.Repository()
|
||||
|
||||
def get_menu_title(self):
|
||||
if self.obj.get_handle():
|
||||
title = self.obj.get_name()
|
||||
if title:
|
||||
title = _('Repository') + ": " + title
|
||||
else:
|
||||
title = _('Repository')
|
||||
else:
|
||||
title = _('New Repository')
|
||||
return title
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.repo-width'
|
||||
self.height_key = 'interface.repo-height'
|
||||
|
||||
self.glade = Glade()
|
||||
|
||||
self.set_window(self.glade.toplevel, None,
|
||||
self.get_menu_title())
|
||||
|
||||
def build_menu_names(self, source):
|
||||
return (_('Edit Repository'), self.get_menu_title())
|
||||
|
||||
def _setup_fields(self):
|
||||
|
||||
self.name = MonitoredEntry(self.glade.get_object("repository_name"),
|
||||
self.obj.set_name, self.obj.get_name,
|
||||
self.db.readonly)
|
||||
|
||||
self.type = MonitoredDataType(self.glade.get_object("repository_type"),
|
||||
self.obj.set_type, self.obj.get_type,
|
||||
self.db.readonly,
|
||||
self.db.get_repository_types(),
|
||||
)
|
||||
|
||||
self.call_number = MonitoredEntry(self.glade.get_object('gid'),
|
||||
self.obj.set_gramps_id,
|
||||
self.obj.get_gramps_id,
|
||||
self.db.readonly)
|
||||
|
||||
self.privacy = PrivacyButton(self.glade.get_object("private"),
|
||||
self.obj, self.db.readonly)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
|
||||
notebook = gtk.Notebook()
|
||||
|
||||
self.addr_tab = AddrEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_address_list())
|
||||
self._add_tab(notebook, self.addr_tab)
|
||||
self.track_ref_for_deletion("addr_tab")
|
||||
|
||||
self.url_tab = WebEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_url_list())
|
||||
self._add_tab(notebook, self.url_tab)
|
||||
self.track_ref_for_deletion("url_tab")
|
||||
|
||||
self.note_tab = NoteTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_note_list(),
|
||||
self.get_menu_title(),
|
||||
notetype=gen.lib.NoteType.REPO)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self.backref_tab = SourceBackRefList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.find_backlink_handles(self.obj.handle))
|
||||
self.backref_list = self._add_tab(notebook, self.backref_tab)
|
||||
self.track_ref_for_deletion("backref_tab")
|
||||
self.track_ref_for_deletion("backref_list")
|
||||
|
||||
self._setup_notebook_tabs(notebook)
|
||||
notebook.show_all()
|
||||
self.glade.get_object("vbox").pack_start(notebook, True, True)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_help_button(self.glade.get_object('help'))
|
||||
self.define_cancel_button(self.glade.get_object('cancel'))
|
||||
self.define_ok_button(self.glade.get_object('ok'), self.save)
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('repository-rebuild', self._do_close)
|
||||
self._add_db_signal('repository-delete', self.check_for_close)
|
||||
|
||||
def save(self, *obj):
|
||||
self.ok_button.set_sensitive(False)
|
||||
if self.object_is_empty():
|
||||
ErrorDialog(_("Cannot save repository"),
|
||||
_("No data exists for this repository. Please "
|
||||
"enter data or cancel the edit."))
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
(uses_dupe_id, id) = self._uses_duplicate_id()
|
||||
if uses_dupe_id:
|
||||
prim_object = self.get_from_gramps_id(id)
|
||||
name = prim_object.get_name()
|
||||
msg1 = _("Cannot save repository. ID already exists.")
|
||||
msg2 = _("You have attempted to use the existing Gramps ID with "
|
||||
"value %(id)s. This value is already used by '"
|
||||
"%(prim_object)s'. Please enter a different ID or leave "
|
||||
"blank to get the next available ID value.") % {
|
||||
'id' : id, 'prim_object' : name }
|
||||
ErrorDialog(msg1, msg2)
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
trans = self.db.transaction_begin()
|
||||
if not self.obj.get_handle():
|
||||
self.db.add_repository(self.obj, trans)
|
||||
msg = _("Add Repository (%s)") % self.obj.get_name()
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_repository_gramps_id())
|
||||
self.db.commit_repository(self.obj, trans)
|
||||
msg = _("Edit Repository (%s)") % self.obj.get_name()
|
||||
|
||||
self.db.transaction_commit(trans, msg)
|
||||
self.close()
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
self.backref_list.close()
|
||||
|
||||
class DeleteRepositoryQuery(object):
|
||||
def __init__(self, dbstate, uistate, repository, sources):
|
||||
self.obj = repository
|
||||
self.db = dbstate.db
|
||||
self.uistate = uistate
|
||||
self.sources = sources
|
||||
|
||||
def query_response(self):
|
||||
trans = self.db.transaction_begin()
|
||||
|
||||
repos_handle_list = [self.obj.get_handle()]
|
||||
|
||||
for handle in self.sources:
|
||||
source = self.db.get_source_from_handle(handle)
|
||||
source.remove_repo_references(repos_handle_list)
|
||||
self.db.commit_source(source, trans)
|
||||
|
||||
self.db.remove_repository(self.obj.get_handle(), trans)
|
||||
self.db.transaction_commit(
|
||||
trans, _("Delete Repository (%s)") % self.obj.get_name())
|
||||
137
src/gui/editors/editsecondary.py
Normal file
137
src/gui/editors/editsecondary.py
Normal file
@@ -0,0 +1,137 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
import ManagedWindow
|
||||
import GrampsDisplay
|
||||
import config
|
||||
from gui.dbguielement import DbGUIElement
|
||||
|
||||
class EditSecondary(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
|
||||
def __init__(self, state, uistate, track, obj, callback=None):
|
||||
"""Create an edit window. Associates a person with the window."""
|
||||
|
||||
self.obj = obj
|
||||
self.dbstate = state
|
||||
self.uistate = uistate
|
||||
self.db = state.db
|
||||
self.callback = callback
|
||||
self.__tabs = []
|
||||
|
||||
ManagedWindow.ManagedWindow.__init__(self, uistate, track, obj)
|
||||
DbGUIElement.__init__(self, self.db)
|
||||
|
||||
self._local_init()
|
||||
self._set_size()
|
||||
|
||||
self._create_tabbed_pages()
|
||||
self._setup_fields()
|
||||
self._connect_signals()
|
||||
self.show()
|
||||
self._post_init()
|
||||
|
||||
def _local_init(self):
|
||||
"""
|
||||
Derived class should do any pre-window initalization in this task.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _post_init(self):
|
||||
"""
|
||||
Derived class should do any post-window initalization in this task.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _connect_signals(self):
|
||||
pass
|
||||
|
||||
def _setup_fields(self):
|
||||
pass
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
pass
|
||||
|
||||
def build_window_key(self, obj):
|
||||
return id(obj)
|
||||
|
||||
def _setup_notebook_tabs(self, notebook):
|
||||
for child in notebook.get_children():
|
||||
label = notebook.get_tab_label(child)
|
||||
page_no = notebook.page_num(child)
|
||||
label.drag_dest_set(0, [], 0)
|
||||
label.connect('drag_motion',
|
||||
self._switch_page_on_dnd,
|
||||
notebook,
|
||||
page_no)
|
||||
child.set_parent_notebook(notebook)
|
||||
notebook.connect('key-press-event', self.key_pressed, notebook)
|
||||
|
||||
def key_pressed(self, obj, event, notebook):
|
||||
"""
|
||||
Handles the key being pressed on the notebook, pass to key press of
|
||||
current page.
|
||||
"""
|
||||
pag = notebook.get_current_page()
|
||||
if not pag == -1:
|
||||
notebook.get_nth_page(pag).key_pressed(obj, event)
|
||||
|
||||
def _switch_page_on_dnd(self, widget, context, x, y, time, notebook, page_no):
|
||||
if notebook.get_current_page() != page_no:
|
||||
notebook.set_current_page(page_no)
|
||||
|
||||
def _add_tab(self, notebook,page):
|
||||
self.__tabs.append(page)
|
||||
notebook.insert_page(page, page.get_tab_widget())
|
||||
page.label.set_use_underline(True)
|
||||
return page
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
pass
|
||||
|
||||
def define_ok_button(self,button,function):
|
||||
button.connect('clicked',function)
|
||||
button.set_sensitive(not self.db.readonly)
|
||||
|
||||
def define_cancel_button(self,button):
|
||||
button.connect('clicked',self.close)
|
||||
|
||||
def define_help_button(self, button, webpage='', section=''):
|
||||
button.connect('clicked', lambda x: GrampsDisplay.help(webpage,
|
||||
section))
|
||||
|
||||
def close(self,*obj):
|
||||
self._cleanup_db_connects()
|
||||
self._cleanup_on_exit()
|
||||
ManagedWindow.ManagedWindow.close(self)
|
||||
|
||||
def _cleanup_db_connects(self):
|
||||
"""
|
||||
All connects that happened to signals of the db must be removed on
|
||||
closed. This implies two things:
|
||||
1. The connects on the main view must be disconnected
|
||||
2. Connects done in subelements must be disconnected
|
||||
"""
|
||||
#cleanup callbackmanager of this editor
|
||||
self._cleanup_callbacks()
|
||||
for tab in [tab for tab in self.__tabs if hasattr(tab, 'callman')]:
|
||||
tab._cleanup_callbacks()
|
||||
268
src/gui/editors/editsource.py
Normal file
268
src/gui/editors/editsource.py
Normal file
@@ -0,0 +1,268 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# Copyright (C) 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
import logging
|
||||
log = logging.getLogger(".")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gen.lib
|
||||
from editprimary import EditPrimary
|
||||
|
||||
from DisplayTabs import (NoteTab, GalleryTab, DataEmbedList,
|
||||
SourceBackRefList, RepoEmbedList)
|
||||
from gui.widgets import MonitoredEntry, PrivacyButton
|
||||
from QuestionDialog import ErrorDialog
|
||||
from glade import Glade
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditSource class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class EditSource(EditPrimary):
|
||||
|
||||
def __init__(self, dbstate, uistate, track, source):
|
||||
|
||||
EditPrimary.__init__(self, dbstate, uistate, track, source,
|
||||
dbstate.db.get_source_from_handle,
|
||||
dbstate.db.get_source_from_gramps_id)
|
||||
|
||||
def empty_object(self):
|
||||
return gen.lib.Source()
|
||||
|
||||
def get_menu_title(self):
|
||||
title = self.obj.get_title()
|
||||
if title:
|
||||
title = _('Source') + ": " + title
|
||||
else:
|
||||
title = _('New Source')
|
||||
return title
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.source-width'
|
||||
self.height_key = 'interface.source-height'
|
||||
assert(self.obj)
|
||||
|
||||
self.glade = Glade()
|
||||
self.set_window(self.glade.toplevel, None,
|
||||
self.get_menu_title())
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_ok_button(self.glade.get_object('ok'),self.save)
|
||||
self.define_cancel_button(self.glade.get_object('cancel'))
|
||||
self.define_help_button(self.glade.get_object('help'))
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('source-rebuild', self._do_close)
|
||||
self._add_db_signal('source-delete', self.check_for_close)
|
||||
|
||||
def _setup_fields(self):
|
||||
self.author = MonitoredEntry(self.glade.get_object("author"),
|
||||
self.obj.set_author, self.obj.get_author,
|
||||
self.db.readonly)
|
||||
|
||||
self.pubinfo = MonitoredEntry(self.glade.get_object("pubinfo"),
|
||||
self.obj.set_publication_info,
|
||||
self.obj.get_publication_info,
|
||||
self.db.readonly)
|
||||
|
||||
self.gid = MonitoredEntry(self.glade.get_object("gid"),
|
||||
self.obj.set_gramps_id,
|
||||
self.obj.get_gramps_id, self.db.readonly)
|
||||
|
||||
self.priv = PrivacyButton(self.glade.get_object("private"), self.obj,
|
||||
self.db.readonly)
|
||||
|
||||
self.abbrev = MonitoredEntry(self.glade.get_object("abbrev"),
|
||||
self.obj.set_abbreviation,
|
||||
self.obj.get_abbreviation,
|
||||
self.db.readonly)
|
||||
|
||||
self.title = MonitoredEntry(self.glade.get_object("source_title"),
|
||||
self.obj.set_title, self.obj.get_title,
|
||||
self.db.readonly)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
notebook = gtk.Notebook()
|
||||
|
||||
self.note_tab = NoteTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_note_list(),
|
||||
self.get_menu_title(),
|
||||
gen.lib.NoteType.SOURCE)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self.gallery_tab = GalleryTab(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_media_list())
|
||||
self._add_tab(notebook, self.gallery_tab)
|
||||
self.track_ref_for_deletion("gallery_tab")
|
||||
|
||||
self.data_tab = DataEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj)
|
||||
self._add_tab(notebook, self.data_tab)
|
||||
self.track_ref_for_deletion("data_tab")
|
||||
|
||||
self.repo_tab = RepoEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.obj.get_reporef_list())
|
||||
self._add_tab(notebook, self.repo_tab)
|
||||
self.track_ref_for_deletion("repo_tab")
|
||||
|
||||
self.backref_list = SourceBackRefList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.find_backlink_handles(self.obj.handle))
|
||||
self.backref_tab = self._add_tab(notebook, self.backref_list)
|
||||
self.track_ref_for_deletion("backref_tab")
|
||||
self.track_ref_for_deletion("backref_list")
|
||||
|
||||
self._setup_notebook_tabs(notebook)
|
||||
notebook.show_all()
|
||||
self.glade.get_object('vbox').pack_start(notebook, True)
|
||||
|
||||
def build_menu_names(self, source):
|
||||
return (_('Edit Source'), self.get_menu_title())
|
||||
|
||||
def save(self, *obj):
|
||||
self.ok_button.set_sensitive(False)
|
||||
if self.object_is_empty():
|
||||
ErrorDialog(_("Cannot save source"),
|
||||
_("No data exists for this source. Please "
|
||||
"enter data or cancel the edit."))
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
(uses_dupe_id, id) = self._uses_duplicate_id()
|
||||
if uses_dupe_id:
|
||||
prim_object = self.get_from_gramps_id(id)
|
||||
name = prim_object.get_title()
|
||||
msg1 = _("Cannot save source. ID already exists.")
|
||||
msg2 = _("You have attempted to use the existing Gramps ID with "
|
||||
"value %(id)s. This value is already used by '"
|
||||
"%(prim_object)s'. Please enter a different ID or leave "
|
||||
"blank to get the next available ID value.") % {
|
||||
'id' : id, 'prim_object' : name }
|
||||
ErrorDialog(msg1, msg2)
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
trans = self.db.transaction_begin()
|
||||
if not self.obj.get_handle():
|
||||
self.db.add_source(self.obj, trans)
|
||||
msg = _("Add Source (%s)") % self.obj.get_title()
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_source_gramps_id())
|
||||
self.db.commit_source(self.obj, trans)
|
||||
msg = _("Edit Source (%s)") % self.obj.get_title()
|
||||
|
||||
self.db.transaction_commit(trans, msg)
|
||||
self.close()
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
self.backref_tab.close()
|
||||
|
||||
class DeleteSrcQuery(object):
|
||||
def __init__(self, dbstate, uistate, source, the_lists):
|
||||
self.source = source
|
||||
self.db = dbstate.db
|
||||
self.uistate = uistate
|
||||
self.the_lists = the_lists
|
||||
|
||||
def query_response(self):
|
||||
trans = self.db.transaction_begin()
|
||||
self.db.disable_signals()
|
||||
|
||||
(person_list, family_list, event_list, place_list, source_list,
|
||||
media_list, repo_list) = self.the_lists
|
||||
|
||||
src_handle_list = [self.source.get_handle()]
|
||||
|
||||
for handle in person_list:
|
||||
person = self.db.get_person_from_handle(handle)
|
||||
person.remove_source_references(src_handle_list)
|
||||
self.db.commit_person(person, trans)
|
||||
|
||||
for handle in family_list:
|
||||
family = self.db.get_family_from_handle(handle)
|
||||
family.remove_source_references(src_handle_list)
|
||||
self.db.commit_family(family, trans)
|
||||
|
||||
for handle in event_list:
|
||||
event = self.db.get_event_from_handle(handle)
|
||||
event.remove_source_references(src_handle_list)
|
||||
self.db.commit_event(event, trans)
|
||||
|
||||
for handle in place_list:
|
||||
place = self.db.get_place_from_handle(handle)
|
||||
place.remove_source_references(src_handle_list)
|
||||
self.db.commit_place(place, trans)
|
||||
|
||||
for handle in source_list:
|
||||
source = self.db.get_source_from_handle(handle)
|
||||
source.remove_source_references(src_handle_list)
|
||||
self.db.commit_source(source, trans)
|
||||
|
||||
for handle in media_list:
|
||||
media = self.db.get_object_from_handle(handle)
|
||||
media.remove_source_references(src_handle_list)
|
||||
self.db.commit_media_object(media, trans)
|
||||
|
||||
for handle in repo_list:
|
||||
repo = self.db.get_repository_from_handle(handle)
|
||||
repo.remove_source_references(src_handle_list)
|
||||
self.db.commit_repository(repo, trans)
|
||||
|
||||
self.db.enable_signals()
|
||||
self.db.remove_source(self.source.get_handle(), trans)
|
||||
self.db.transaction_commit(
|
||||
trans, _("Delete Source (%s)") % self.source.get_title())
|
||||
219
src/gui/editors/editsourceref.py
Normal file
219
src/gui/editors/editsourceref.py
Normal file
@@ -0,0 +1,219 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gen.lib
|
||||
from glade import Glade
|
||||
from DisplayTabs import (NoteTab, GalleryTab, SourceBackRefList,
|
||||
DataEmbedList, RepoEmbedList)
|
||||
from gui.widgets import (PrivacyButton, MonitoredEntry, MonitoredMenu,
|
||||
MonitoredDate)
|
||||
from editreference import RefTab, EditReference
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditSourceRef class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditSourceRef(EditReference):
|
||||
|
||||
def __init__(self, state, uistate, track, source, source_ref, update):
|
||||
|
||||
EditReference.__init__(self, state, uistate, track, source,
|
||||
source_ref, update)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.event-ref-width'
|
||||
self.height_key = 'interface.event-ref-height'
|
||||
|
||||
self.top = Glade()
|
||||
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object('source_title'),
|
||||
_('Source Reference Editor'))
|
||||
|
||||
self.define_warn_box(self.top.get_object("warn_box"))
|
||||
self.define_expander(self.top.get_object("src_expander"))
|
||||
|
||||
tblref = self.top.get_object('table67')
|
||||
notebook = self.top.get_object('notebook_ref')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.reftab = RefTab(self.dbstate, self.uistate, self.track,
|
||||
_('General'), tblref)
|
||||
tblref = self.top.get_object('table68')
|
||||
notebook = self.top.get_object('notebook_src')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.primtab = RefTab(self.dbstate, self.uistate, self.track,
|
||||
_('General'), tblref)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.define_ok_button(self.top.get_object('ok'),self.ok_clicked)
|
||||
self.define_cancel_button(self.top.get_object('cancel'))
|
||||
self.define_help_button(self.top.get_object("help"))
|
||||
|
||||
def _connect_db_signals(self):
|
||||
"""
|
||||
Connect any signals that need to be connected.
|
||||
Called by the init routine of the base class (_EditPrimary).
|
||||
"""
|
||||
self._add_db_signal('source-rebuild', self.close)
|
||||
self._add_db_signal('source-delete', self.check_for_close)
|
||||
#note: at the moment, a source cannot be updated while an editor with
|
||||
# that source shown is open. So no need to connect to source-update
|
||||
|
||||
def _setup_fields(self):
|
||||
self.ref_privacy = PrivacyButton(
|
||||
self.top.get_object('privacy'), self.source_ref, self.db.readonly)
|
||||
|
||||
self.volume = MonitoredEntry(
|
||||
self.top.get_object("volume"), self.source_ref.set_page,
|
||||
self.source_ref.get_page, self.db.readonly)
|
||||
|
||||
self.gid = MonitoredEntry(
|
||||
self.top.get_object('gid'), self.source.set_gramps_id,
|
||||
self.source.get_gramps_id,self.db.readonly)
|
||||
|
||||
self.source_privacy = PrivacyButton(
|
||||
self.top.get_object("private"),
|
||||
self.source, self.db.readonly)
|
||||
|
||||
self.title = MonitoredEntry(
|
||||
self.top.get_object('title'),
|
||||
self.source.set_title,
|
||||
self.source.get_title,
|
||||
self.db.readonly)
|
||||
|
||||
self.abbrev = MonitoredEntry(
|
||||
self.top.get_object('abbrev'), self.source.set_abbreviation,
|
||||
self.source.get_abbreviation,self.db.readonly)
|
||||
|
||||
self.author = MonitoredEntry(
|
||||
self.top.get_object('author'), self.source.set_author,
|
||||
self.source.get_author,self.db.readonly)
|
||||
|
||||
self.pubinfo = MonitoredEntry(
|
||||
self.top.get_object('pub_info'), self.source.set_publication_info,
|
||||
self.source.get_publication_info,self.db.readonly)
|
||||
|
||||
self.type_mon = MonitoredMenu(
|
||||
self.top.get_object('confidence'),
|
||||
self.source_ref.set_confidence_level,
|
||||
self.source_ref.get_confidence_level, [
|
||||
(_('Very Low'), gen.lib.SourceRef.CONF_VERY_LOW),
|
||||
(_('Low'), gen.lib.SourceRef.CONF_LOW),
|
||||
(_('Normal'), gen.lib.SourceRef.CONF_NORMAL),
|
||||
(_('High'), gen.lib.SourceRef.CONF_HIGH),
|
||||
(_('Very High'), gen.lib.SourceRef.CONF_VERY_HIGH)],
|
||||
self.db.readonly)
|
||||
|
||||
self.date = MonitoredDate(
|
||||
self.top.get_object("date_entry"),
|
||||
self.top.get_object("date_stat"),
|
||||
self.source_ref.get_date_object(),
|
||||
self.uistate,
|
||||
self.track,
|
||||
self.db.readonly)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
Create the notebook tabs and inserts them into the main
|
||||
window.
|
||||
"""
|
||||
notebook_src = self.top.get_object('notebook_src')
|
||||
notebook_ref = self.top.get_object('notebook_ref')
|
||||
|
||||
self._add_tab(notebook_src, self.primtab)
|
||||
self._add_tab(notebook_ref, self.reftab)
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook_src,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_note_list(),
|
||||
notetype=gen.lib.NoteType.SOURCE))
|
||||
|
||||
self.gallery_tab = self._add_tab(
|
||||
notebook_src,
|
||||
GalleryTab(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_media_list()))
|
||||
|
||||
self.data_tab = self._add_tab(
|
||||
notebook_src,
|
||||
DataEmbedList(self.dbstate, self.uistate, self.track,
|
||||
self.source))
|
||||
|
||||
self.repo_tab = self._add_tab(
|
||||
notebook_src,
|
||||
RepoEmbedList(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_reporef_list()))
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook_src,
|
||||
SourceBackRefList(self.dbstate,self.uistate, self.track,
|
||||
self.db.find_backlink_handles(self.source.handle),
|
||||
self.enable_warnbox
|
||||
))
|
||||
|
||||
self.comment_tab = self._add_tab(
|
||||
notebook_ref,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source_ref.get_note_list(),
|
||||
notetype=gen.lib.NoteType.SOURCEREF))
|
||||
|
||||
self._setup_notebook_tabs( notebook_src)
|
||||
self._setup_notebook_tabs( notebook_ref)
|
||||
|
||||
def build_menu_names(self,sourceref):
|
||||
if self.source:
|
||||
source_name = self.source.get_title()
|
||||
submenu_label = _('Source: %s') % source_name
|
||||
else:
|
||||
submenu_label = _('New Source')
|
||||
return (_('Source Reference Editor'),submenu_label)
|
||||
|
||||
def ok_clicked(self, obj):
|
||||
|
||||
trans = self.db.transaction_begin()
|
||||
if self.source.handle:
|
||||
self.db.commit_source(self.source,trans)
|
||||
self.db.transaction_commit(trans,_("Modify Source"))
|
||||
else:
|
||||
self.db.add_source(self.source,trans)
|
||||
self.db.transaction_commit(trans,_("Add Source"))
|
||||
|
||||
if self.update:
|
||||
self.update(self.source_ref,self.source)
|
||||
|
||||
self.close()
|
||||
96
src/gui/editors/editurl.py
Normal file
96
src/gui/editors/editurl.py
Normal file
@@ -0,0 +1,96 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from editsecondary import EditSecondary
|
||||
from gui.widgets import MonitoredEntry, PrivacyButton, MonitoredDataType
|
||||
from glade import Glade
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditUrl class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class EditUrl(EditSecondary):
|
||||
|
||||
def __init__(self, dbstate, uistate, track, name, url, callback):
|
||||
|
||||
EditSecondary.__init__(self, dbstate, uistate, track,
|
||||
url, callback)
|
||||
|
||||
def _local_init(self):
|
||||
self.width_key = 'interface.url-width'
|
||||
self.height_key = 'interface.url-height'
|
||||
|
||||
self.top = Glade()
|
||||
self.jump = self.top.get_object('jump')
|
||||
|
||||
self.set_window(self.top.toplevel,
|
||||
self.top.get_object("title"),
|
||||
_('Internet Address Editor'))
|
||||
|
||||
def _connect_signals(self):
|
||||
self.jump.connect('clicked', self.jump_to)
|
||||
self.define_cancel_button(self.top.get_object('button125'))
|
||||
self.define_ok_button(self.top.get_object('button124'), self.save)
|
||||
self.define_help_button(self.top.get_object('button130'))
|
||||
|
||||
def jump_to(self, obj):
|
||||
if self.obj.get_path():
|
||||
import GrampsDisplay
|
||||
GrampsDisplay.url(self.obj.get_path())
|
||||
|
||||
def _setup_fields(self):
|
||||
self.des = MonitoredEntry(self.top.get_object("url_des"),
|
||||
self.obj.set_description,
|
||||
self.obj.get_description, self.db.readonly)
|
||||
|
||||
self.addr = MonitoredEntry(self.top.get_object("url_addr"),
|
||||
self.obj.set_path, self.obj.get_path,
|
||||
self.db.readonly)
|
||||
|
||||
self.priv = PrivacyButton(self.top.get_object("priv"),
|
||||
self.obj, self.db.readonly)
|
||||
|
||||
self.type_sel = MonitoredDataType(self.top.get_object("type"),
|
||||
self.obj.set_type,
|
||||
self.obj.get_type, self.db.readonly)
|
||||
|
||||
def build_menu_names(self, obj):
|
||||
etitle =_('Internet Address Editor')
|
||||
return (etitle, etitle)
|
||||
|
||||
def save(self,*obj):
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
412
src/gui/editors/objectentries.py
Normal file
412
src/gui/editors/objectentries.py
Normal file
@@ -0,0 +1,412 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
import cPickle as pickle
|
||||
|
||||
import logging
|
||||
_LOG = logging.getLogger(".objectentries")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
from pango import ELLIPSIZE_END
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gen.lib import (Place, MediaObject, Note)
|
||||
from editplace import EditPlace
|
||||
from editmedia import EditMedia
|
||||
from editnote import EditNote
|
||||
from gui.selectors import SelectorFactory
|
||||
from DdTargets import DdTargets
|
||||
from Errors import WindowActiveError
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# ObjEntry
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class ObjEntry(object):
|
||||
"""
|
||||
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
|
||||
"""
|
||||
EMPTY_TEXT = ""
|
||||
EMPTY_TEXT_RED = ""
|
||||
EDIT_STR = ""
|
||||
SHARE_STR = ""
|
||||
ADD_STR = ""
|
||||
DEL_STR = ""
|
||||
|
||||
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
|
||||
|
||||
#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)
|
||||
self.label.set_ellipsize(ELLIPSIZE_END)
|
||||
|
||||
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.share.set_tooltip_text(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.add_edt.set_tooltip_text(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.share.set_tooltip_text(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.add_edt.set_tooltip_text(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 = SelectorFactory('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):
|
||||
cls = SelectorFactory('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())
|
||||
#String must be unicode for truncation to work for non ascii characters
|
||||
txt = unicode(txt)
|
||||
if len(txt) > 35:
|
||||
txt = txt[:35] + "..."
|
||||
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 = SelectorFactory('Note')
|
||||
return cls(self.dbstate, self.uistate, self.track)
|
||||
@@ -52,7 +52,7 @@ import config
|
||||
from QuestionDialog import ErrorDialog
|
||||
from gui.pluginmanager import GuiPluginManager
|
||||
from DdTargets import DdTargets
|
||||
from Editors import EditPlace, DeletePlaceQuery
|
||||
from gui.editors import EditPlace, DeletePlaceQuery
|
||||
from Filters.SideBar import PlaceSidebarFilter
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -37,4 +37,4 @@ from toolcomboentry import *
|
||||
from validatedcomboentry import *
|
||||
from validatedmaskedentry import *
|
||||
from valueaction import *
|
||||
from valuetoolitem import *
|
||||
from valuetoolitem import *
|
||||
|
||||
Reference in New Issue
Block a user