2008-02-07 Raphael Ackermann <raphael.ackermann@gmail.com>

* src/Editors/_EditPerson.py: pylint fixes & doc fixes
	fixed 0001347: double gid should not be allowed for Person View
	Still open for all the other list views.

svn: r10001
This commit is contained in:
Raphael Ackermann 2008-02-07 08:34:47 +00:00
parent 146e89876d
commit 8c0779eabb
2 changed files with 135 additions and 71 deletions

View File

@ -1,3 +1,8 @@
2008-02-07 Raphael Ackermann <raphael.ackermann@gmail.com>
* src/Editors/_EditPerson.py: pylint fixes & doc fixes
fixed 0001347: double gid should not be allowed for Person View
Still open for all the other list views.
2008-02-05 Raphael Ackermann <raphael.ackermann@gmail.com> 2008-02-05 Raphael Ackermann <raphael.ackermann@gmail.com>
* src/data/tips.xml.in: remove checkpoint reference * src/data/tips.xml.in: remove checkpoint reference
* src/plugins/Makefile.am: remove checkpoint reference * src/plugins/Makefile.am: remove checkpoint reference

View File

@ -39,6 +39,7 @@ from gettext import gettext as _
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import gtk import gtk
from gtk import glade
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -55,12 +56,14 @@ import Errors
from gen.utils import set_birth_death_index from gen.utils import set_birth_death_index
from _EditPrimary import EditPrimary from Editors._EditPrimary import EditPrimary
from QuestionDialog import * import Config
from DisplayTabs import \ from QuestionDialog import ErrorDialog, ICON
PersonEventEmbedList,NameEmbedList,SourceEmbedList,AttrEmbedList,\
AddrEmbedList,NoteTab,GalleryTab,WebEmbedList,PersonRefEmbedList, \ from DisplayTabs import (PersonEventEmbedList, NameEmbedList, SourceEmbedList,
LdsEmbedList,PersonBackRefList AttrEmbedList, AddrEmbedList, NoteTab, GalleryTab,
WebEmbedList, PersonRefEmbedList, LdsEmbedList,
PersonBackRefList)
from ReportBase import CATEGORY_QR_PERSON from ReportBase import CATEGORY_QR_PERSON
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -79,8 +82,10 @@ _use_patronymic = set(
class EditPerson(EditPrimary): class EditPerson(EditPrimary):
""" """
The EditPerson dialog is derived from the EditPrimary class. It The EditPerson dialog is derived from the EditPrimary class.
allos for the editing of the primary object type of Person.
It allows for the editing of the primary object type of Person.
""" """
use_patronymic = locale.getlocale(locale.LC_TIME)[0] in _use_patronymic use_patronymic = locale.getlocale(locale.LC_TIME)[0] in _use_patronymic
@ -88,15 +93,20 @@ class EditPerson(EditPrimary):
def __init__(self, state, uistate, track, person, callback=None): def __init__(self, state, uistate, track, person, callback=None):
""" """
Creates an EditPerson window. Associates a person with the window. Create an EditPerson window.
Associates a person with the window.
""" """
EditPrimary.__init__(self, state, uistate, track, person, EditPrimary.__init__(self, state, uistate, track, person,
state.db.get_person_from_handle, callback) state.db.get_person_from_handle, callback)
def empty_object(self): def empty_object(self):
""" """
Returns an empty Person object for comparison for changes. This Return an empty Person object for comparison for changes.
is used by the base class (EditPrimary)
This is used by the base class (EditPrimary).
""" """
return gen.lib.Person() return gen.lib.Person()
@ -110,9 +120,12 @@ class EditPerson(EditPrimary):
def _local_init(self): def _local_init(self):
""" """
Local initialization function. Performs basic initialization, Performs basic initialization, including setting up widgets and the
including setting up widgets and the glade interface. This is called glade interface.
by the base class of EditPrimary, and overridden here.
Local initialization function.
This is called by the base class of EditPrimary, and overridden here.
""" """
self.pname = self.obj.get_primary_name() self.pname = self.obj.get_primary_name()
self.should_guess_gender = (not self.obj.get_gramps_id() and self.should_guess_gender = (not self.obj.get_gramps_id() and
@ -121,9 +134,10 @@ class EditPerson(EditPrimary):
self.load_obj = None self.load_obj = None
self.load_rect = None self.load_rect = None
self.top = gtk.glade.XML(const.PERSON_GLADE, "edit_person", "gramps") self.top = glade.XML(const.PERSON_GLADE, "edit_person", "gramps")
self.set_window(self.top.get_widget("edit_person"), None, self.get_menu_title()) self.set_window(self.top.get_widget("edit_person"), None,
self.get_menu_title())
width = Config.get(Config.PERSON_WIDTH) width = Config.get(Config.PERSON_WIDTH)
height = Config.get(Config.PERSON_HEIGHT) height = Config.get(Config.PERSON_HEIGHT)
self.window.set_default_size(width, height) self.window.set_default_size(width, height)
@ -136,10 +150,13 @@ class EditPerson(EditPrimary):
def _post_init(self): def _post_init(self):
""" """
Post initalization function. Handles any initialization that Handle any initialization that needs to be done after the interface is
needs to be done after the interface is brought up. This called brought up.
by _EditPrimary's init routine, and overridden in the derived
class (this class) Post initalization function.
This is called by _EditPrimary's init routine, and overridden in the
derived class (this class).
""" """
self.load_person_image() self.load_person_image()
if self.pname.get_surname() and not self.pname.get_first_name(): if self.pname.get_surname() and not self.pname.get_first_name():
@ -149,8 +166,10 @@ class EditPerson(EditPrimary):
def _connect_signals(self): def _connect_signals(self):
""" """
Connects any signals that need to be connected. Called by the Connect any signals that need to be connected.
init routine of the base class (_EditPrimary).
Called by the init routine of the base class (_EditPrimary).
""" """
self.define_cancel_button(self.top.get_widget("button15")) self.define_cancel_button(self.top.get_widget("button15"))
self.define_ok_button(self.top.get_widget("ok"), self.save) self.define_ok_button(self.top.get_widget("ok"), self.save)
@ -169,7 +188,10 @@ class EditPerson(EditPrimary):
self._add_db_signal('family-add', self.family_change) self._add_db_signal('family-add', self.family_change)
def family_change(self, handle_list=[]): def family_change(self, handle_list=[]):
"""Callback for family change signals. This should rebuild the """
Callback for family change signals.
This should rebuild the
backreferences to family in person when: backreferences to family in person when:
1)a family the person is parent of changes. Person could have 1)a family the person is parent of changes. Person could have
been removed been removed
@ -177,6 +199,7 @@ class EditPerson(EditPrimary):
removed removed
3)a family is changed. The person could be added as child or 3)a family is changed. The person could be added as child or
parent parent
""" """
#As this would be an extensive check, we choose the easy path and #As this would be an extensive check, we choose the easy path and
# rebuild family backreferences on all family changes # rebuild family backreferences on all family changes
@ -193,9 +216,11 @@ class EditPerson(EditPrimary):
def _setup_fields(self): def _setup_fields(self):
""" """
Connects the GrampsWidget objects to field in the interface. This Connect the GrampsWidget objects to field in the interface.
allows the widgets to keep the data in the attached Person object
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. up to date at all times, eliminating a lot of need in 'save' routine.
""" """
self.private = GrampsWidgets.PrivacyButton( self.private = GrampsWidgets.PrivacyButton(
@ -285,9 +310,7 @@ class EditPerson(EditPrimary):
def _create_tabbed_pages(self): def _create_tabbed_pages(self):
""" """
Creates the notebook tabs and inserts them into the main Create the notebook tabs and insert them into the main window.
window.
""" """
notebook = gtk.Notebook() notebook = gtk.Notebook()
@ -333,7 +356,8 @@ class EditPerson(EditPrimary):
WebEmbedList(self.dbstate, self.uistate, self.track, WebEmbedList(self.dbstate, self.uistate, self.track,
self.obj.get_url_list())) self.obj.get_url_list()))
self.person_ref_list = PersonRefEmbedList(self.dbstate, self.uistate, self.track, self.person_ref_list = PersonRefEmbedList(self.dbstate, self.uistate,
self.track,
self.obj.get_person_ref_list()) self.obj.get_person_ref_list())
self.pref_list = self._add_tab(notebook, self.person_ref_list) self.pref_list = self._add_tab(notebook, self.person_ref_list)
self.lds_list = self._add_tab( self.lds_list = self._add_tab(
@ -386,23 +410,29 @@ class EditPerson(EditPrimary):
def build_menu_names(self, person): def build_menu_names(self, person):
""" """
Provides the information need by the base class to define the Provide the information needed by the base class to define the
window management menu entries. window management menu entries.
""" """
return (_('Edit Person'), self.get_menu_title()) return (_('Edit Person'), self.get_menu_title())
def _image_callback(self, ref, obj): def _image_callback(self, ref, obj):
""" """
Called when a media reference had been edited. This allows for Called when a media reference had been edited.
the updating image on the main form which has just been modified.
This allows for the updating image on the main form which has just
been modified.
""" """
self.load_photo(obj.get_path(), ref.get_rectangle()) self.load_photo(obj.get_path(), ref.get_rectangle())
def _image_button_press(self, obj, event): def _image_button_press(self, obj, event):
""" """
Button press event that is caught when a button has been Button press event that is caught when a button has been pressed while
pressed while on the image on the main form. This does not apply on the image on the main form.
to the images in galleries, just 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: if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
@ -417,7 +447,7 @@ class EditPerson(EditPrimary):
try: try:
EditMediaRef(self.dbstate, self.uistate, self.track, EditMediaRef(self.dbstate, self.uistate, self.track,
media_obj, media_ref, self._image_callback) media_obj, media_ref, self._image_callback)
except Errors.WindowActiveError, msg: except Errors.WindowActiveError:
pass pass
elif event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: elif event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
@ -430,8 +460,8 @@ class EditPerson(EditPrimary):
def _show_popup(self, photo, event): def _show_popup(self, photo, event):
""" """
Look for right-clicks on a picture and create a popup Look for right-clicks on a picture and create a popup menu of the
menu of the available actions. available actions.
""" """
menu = gtk.Menu() menu = gtk.Menu()
@ -449,7 +479,7 @@ class EditPerson(EditPrimary):
def _popup_view_photo(self, obj): def _popup_view_photo(self, obj):
""" """
Open this picture in the default picture viewer Open this picture in the default picture viewer.
""" """
media_list = self.obj.get_media_list() media_list = self.obj.get_media_list()
if media_list: if media_list:
@ -459,7 +489,7 @@ class EditPerson(EditPrimary):
def _popup_change_description(self, obj): def _popup_change_description(self, obj):
""" """
Brings up the EditMediaRef dialog for the image on the main form. Bring up the EditMediaRef dialog for the image on the main form.
""" """
media_list = self.obj.get_media_list() media_list = self.obj.get_media_list()
if media_list: if media_list:
@ -472,9 +502,10 @@ class EditPerson(EditPrimary):
media_obj, media_ref, self._image_callback) media_obj, media_ref, self._image_callback)
def _top_contextmenu(self): def _top_contextmenu(self):
'''override from base class, the menuitems and actiongroups for the """
top of context menu Override from base class, the menuitems and actiongroups for the top
''' of context menu.
"""
self.all_action = gtk.ActionGroup("/PersonAll") self.all_action = gtk.ActionGroup("/PersonAll")
self.home_action = gtk.ActionGroup("/PersonHome") self.home_action = gtk.ActionGroup("/PersonHome")
@ -497,8 +528,9 @@ class EditPerson(EditPrimary):
return ui_top_cm, [self.all_action, self.home_action] return ui_top_cm, [self.all_action, self.home_action]
def _post_build_popup_ui(self): def _post_build_popup_ui(self):
'''override base class, make inactive home action if not needed """
''' Override base class, make inactive home action if not needed.
"""
if self.dbstate.db.get_default_person() and \ if self.dbstate.db.get_default_person() and \
self.obj.get_handle() == \ self.obj.get_handle() == \
self.dbstate.db.get_default_person().get_handle(): self.dbstate.db.get_default_person().get_handle():
@ -531,7 +563,9 @@ class EditPerson(EditPrimary):
return False return False
def load_photo(self, path, rectangle=None): def load_photo(self, path, rectangle=None):
"""loads, scales, and displays the person's main photo from the path""" """
Load, scale and display the person's main photo from the path.
"""
self.load_obj = path self.load_obj = path
self.load_rect = rectangle self.load_rect = rectangle
if path == None: if path == None:
@ -572,21 +606,22 @@ class EditPerson(EditPrimary):
if gender >= 0: if gender >= 0:
self.obj.set_gender(gender) self.obj.set_gender(gender)
def _check_and_update_id(self): def _person_uses_duplicate_id(self):
original = self.db.get_person_from_handle(self.obj.get_handle()) """
Check whether a changed or added person ID already exists in the DB.
if original and original.get_gramps_id() != self.obj.get_gramps_id(): Return True if a duplicate person ID has been detected.
"""
original = self.db.get_person_from_handle(self.obj.get_handle())
if original and original.get_gramps_id() == self.obj.get_gramps_id():
return (False, '', '')
else:
idval = self.obj.get_gramps_id() idval = self.obj.get_gramps_id()
person = self.db.get_person_from_gramps_id(idval) person = self.db.get_person_from_gramps_id(idval)
if person: if person:
name = self.nd.display(person) name = self.nd.display(person)
msg1 = _("GRAMPS ID value was not changed.") return (True, idval, name)
msg2 = _("You have attempted to change the GRAMPS ID " return (False, '', '')
"to a value of %(grampsid)s. This value is "
"already used by %(person)s.") % {
'grampsid' : idval,
'person' : name }
WarningDialog(msg1, msg2)
def _update_family_ids(self, trans): def _update_family_ids(self, trans):
# Update each of the families child lists to reflect any # Update each of the families child lists to reflect any
@ -668,7 +703,18 @@ class EditPerson(EditPrimary):
trans = self.db.transaction_begin() trans = self.db.transaction_begin()
self._check_and_update_id() (uses_dupe_id, person_id, name) = self._person_uses_duplicate_id()
if uses_dupe_id:
msg1 = _("Cannot save person. ID already exists.")
msg2 = _("You have attempted to use the existing GRAMPS ID with "
"value %(person_id)s. This value is already used by "
"%(person)s. Please enter a different ID or leave "
"blank to get the next available ID value.") % {
'person_id' : person_id, 'person' : name }
ErrorDialog(msg1, msg2)
self.ok_button.set_sensitive(True)
return
self._update_family_ids(trans) self._update_family_ids(trans)
if not self.obj.get_handle(): if not self.obj.get_handle():
@ -686,19 +732,23 @@ class EditPerson(EditPrimary):
def _edit_name_clicked(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 Called when the edit name button is clicked for the primary name
on the main form (not in the names tab). Brings up the EditName on the main form (not in the names tab).
dialog for this name.
""" """
from Editors import EditName from Editors import EditName
EditName(self.dbstate, self.uistate, self.track, EditName(self.dbstate, self.uistate, self.track,
self.pname, self._update_name) self.pname, self._update_name)
def _update_name(self, name): def _update_name(self):
""" """
Called when the primary name has been changed by the EditName Called when the primary name has been changed by the EditName
dialog. This allows us to update the main form in response to dialog.
any changes.
This allows us to update the main form in response to any changes.
""" """
for obj in (self.suffix, self.prefix, self.given, self.title, for obj in (self.suffix, self.prefix, self.given, self.title,
self.ntype_field, self.surname_field, self.call): self.ntype_field, self.surname_field, self.call):
@ -706,8 +756,10 @@ class EditPerson(EditPrimary):
def load_person_image(self): def load_person_image(self):
""" """
Loads the primary image into the main form if it exists. Load the primary image into the main form if it exists.
Used as callback on Gallery Tab too. Used as callback on Gallery Tab too.
""" """
media_list = self.obj.get_media_list() media_list = self.obj.get_media_list()
if media_list: if media_list:
@ -726,8 +778,10 @@ class EditPerson(EditPrimary):
self.load_photo(None) self.load_photo(None)
def birth_dates_in_order(self, child_ref_list): 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.""" Check any *valid* birthdates in the list to insure that they are in
numerically increasing order.
"""
inorder = True inorder = True
prev_date = 0 prev_date = 0
handle_list = [ref.ref for ref in child_ref_list] handle_list = [ref.ref for ref in child_ref_list]
@ -747,9 +801,14 @@ class EditPerson(EditPrimary):
return inorder return inorder
def reorder_child_ref_list(self, person, child_ref_list): 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 Reorder the child list to put the specified person in his/her
as short a distance as possible.""" 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): if self.birth_dates_in_order(child_ref_list):
return(child_ref_list) return(child_ref_list)
@ -774,7 +833,7 @@ class EditPerson(EditPrimary):
event = self.db.get_event_from_handle(event_ref.ref) event = self.db.get_event_from_handle(event_ref.ref)
other_bday = event.get_date_object().get_sort_value() other_bday = event.get_date_object().get_sort_value()
if other_bday == 0: if other_bday == 0:
continue; continue
if person_bday < other_bday: if person_bday < other_bday:
target = i target = i
else: else:
@ -789,7 +848,7 @@ class EditPerson(EditPrimary):
event = self.db.get_event_from_handle(event_ref.ref) event = self.db.get_event_from_handle(event_ref.ref)
other_bday = event.get_date_object().get_sort_value() other_bday = event.get_date_object().get_sort_value()
if other_bday == "99999999": if other_bday == "99999999":
continue; continue
if person_bday > other_bday: if person_bday > other_bday:
target = i target = i
else: else:
@ -809,7 +868,7 @@ class EditPerson(EditPrimary):
class GenderDialog(gtk.MessageDialog): class GenderDialog(gtk.MessageDialog):
def __init__(self,parent=None): def __init__(self, parent=None):
gtk.MessageDialog.__init__(self, gtk.MessageDialog.__init__(self,
parent, parent,
flags=gtk.DIALOG_MODAL, flags=gtk.DIALOG_MODAL,