Various enhancements:

* Modified Event object to include references to Citations
* Implemented database upgrade for Events (upgrade for Media had already been done)
* Enhanced database upgrade to do backlinks
* Modified Media object to remove sourceref
* Implemented citations bottombar gramplet
* Some minor fixes and improvements

svn: r18054
This commit is contained in:
Tim G L Lyons 2011-08-23 16:54:03 +00:00
parent e26c5325e0
commit 165625715d
24 changed files with 1158 additions and 261 deletions

View File

@ -36,14 +36,17 @@ if config.get('preferences.use-bsddb3'):
from bsddb3 import db
else:
from bsddb import db
from gen.db import BSDDBTxn
from gen.db import BSDDBTxn, DbTxn
from gen.lib.nameorigintype import NameOriginType
from gen.db.write import _mkname, SURNAMES
num_citations = 0
def gramps_upgrade_16(self):
"""Upgrade database from version 15 to 16. This upgrade converts all
SourceRef child objects to Citation Primary objects.
"""
global num_citations
length = (len(self.note_map) + len(self.person_map) +
len(self.event_map) + len(self.family_map) +
len(self.repository_map) + len(self.media_map) +
@ -53,62 +56,220 @@ def gramps_upgrade_16(self):
LOG.debug("self %s" % self)
LOG.debug("self.find_next_citation_gramps_id %s" %
self.find_next_citation_gramps_id)
t = time.time()
num_citations = 0
# ---------------------------------
# Modify Media
# ---------------------------------
for media_handle in self.media_map.keys():
media = self.media_map[media_handle]
LOG.debug("upgrade media %s" % media[4])
if len(media) == 12:
LOG.debug(" len == 12")
with DbTxn(_("convert a media record"), self, batch=True,
no_magic=True) as transaction:
# FIXME: This should be a single transaction, so that
# either the whole of the media object is updated or none is
# but it doesn't seem to work like that because if
# update_refernce_map fails, the put of the new_media
# remains committed.
# (1) create each citation
# (2) update the Media to reference the Citations
# (3) remove backlinks for references from Media to Source
# (4) add backlinks for references from Media to Citations
# (5) add backlinks for references from Citation to Source
(handle, gramps_id, path, mime, desc,
attribute_list, source_list, note_list, change,
date, tag_list, private) = media
new_citation_list = convert_sourceref_to_citation_15(self,
source_list)
new_citation_list = convert_source_list_to_citation_list_16(
self, source_list, transaction)
new_attribute_list = upgrade_attribute_list_16(
self, attribute_list, transaction)
new_media = (handle, gramps_id, path, mime, desc,
attribute_list, source_list, note_list, change,
date, tag_list, new_citation_list, private)
new_attribute_list, new_citation_list, note_list,
change, date, tag_list, private)
LOG.debug(" upgrade new_media %s" % [new_media])
with BSDDBTxn(self.env, self.media_map) as txn:
txn.put(str(handle), new_media)
txn.put(str(handle), new_media, txn=transaction)
# (3) remove backlinks for references from Media to Source
# (4) add backlinks for references from Media to Citations
# (get_object is really get_MediaObject !)
LOG.debug(" update ref map media %s" % [handle,
self.get_object_from_handle(handle) ])
with BSDDBTxn(self.env) as txn:
self.update_reference_map(
self.get_object_from_handle(handle),
transaction,
txn.txn)
self.update()
def convert_sourceref_to_citation_15(self, source_list):
new_citation_list = []
LOG.debug(" convert_sourceref_to_citation_15")
for source in source_list:
LOG.debug(" old sourceref %s" % [source])
(date, private, note_list, confidence, ref, page) = source
new_handle = self.create_id()
new_media_list = []
new_data_map = {}
new_change = time.time()
LOG.debug(" self %s" % [self])
LOG.debug("Media upgrade %d citations upgraded in %d seconds" %
(num_citations, int(time.time()-t)))
# FIXME: I don't understand why I can't use find_next_citation_gramps_id.
# Attempting to use it fails. This seems to be because cid_trans
# is not initialised properly. However I don't understand how this
# is ever initialised.
# Also, self.cmap_index does not seem to be initialised, but
# again I don't see how it is initialised for
# find_next_citation_gramps_id
# Should self.citation_map and/or cmap_index be committed to the
# database after being updated?
LOG.debug(" cmap_index %s" % self.cmap_index)
LOG.debug(" len(self.citation_map) %s" % len(self.citation_map))
(self.cmap_index, new_gramps_id) = \
__find_next_gramps_id(self, self.citation_prefix,
self.cmap_index)
LOG.debug(" new_gramps_id %s" % new_gramps_id)
new_citation = (new_handle, new_gramps_id,
date, page, confidence, ref, note_list, new_media_list,
new_data_map, new_change, private)
LOG.debug(" new_citation %s" % [new_citation])
# ---------------------------------
# Modify Events
# ---------------------------------
upgrade_time = 0
backlink_time = 0
for event_handle in self.event_map.keys():
t1 = time.time()
event = self.event_map[event_handle]
with DbTxn(_("convert a media record"), self, batch=True,
no_magic=True) as transaction:
(handle, gramps_id, the_type, date, description, place,
source_list, note_list, media_list, attribute_list,
change, private) = event
if source_list:
new_citation_list = convert_source_list_to_citation_list_16(
self, source_list, transaction)
else:
new_citation_list = []
if attribute_list:
attribute_list = upgrade_attribute_list_16(
self, attribute_list, transaction)
if media_list:
media_list = upgrade_media_list_16(
self, media_list, transaction)
# FIXME: events also have sources for places
if source_list or attribute_list or media_list:
LOG.debug("upgrade event %s: %s" % (event[1], event [4]))
new_event = (handle, gramps_id, the_type, date, description, place,
new_citation_list, note_list, media_list,
attribute_list,
change, private)
# LOG.debug(" upgrade new_event %s" % [new_event])
with BSDDBTxn(self.env, self.event_map) as txn:
txn.put(str(handle), new_event, txn=transaction)
t2 = time.time()
upgrade_time += t2 - t1
# remove backlinks for references from Media to Source
# add backlinks for references from Media to Citations
if source_list or attribute_list or media_list:
LOG.debug(" upgrade backlinks %s" %
[source_list, attribute_list, media_list])
with BSDDBTxn(self.env) as txn:
self.update_reference_map(
self.get_event_from_handle(handle),
transaction,
txn.txn)
self.update()
t3 = time.time()
backlink_time += t3 - t2
LOG.debug("%d events upgraded with %d citations in %d seconds. "
"Backlinks took %d seconds" %
(len(self.event_map.keys()), num_citations,
int(upgrade_time), int(backlink_time)))
# FIXME: some useful code snipetts for building an information dialogue
# about the speed of datatbase upgrade.
# self.data_newobject = [0] * 9
# self.data_newobject[self.key2data[key]] += 1
# key2string = {
# PERSON_KEY : _(' People: %d\n'),
# FAMILY_KEY : _(' Families: %d\n'),
# SOURCE_KEY : _(' Sources: %d\n'),
# EVENT_KEY : _(' Events: %d\n'),
# MEDIA_KEY : _(' Media Objects: %d\n'),
# PLACE_KEY : _(' Places: %d\n'),
# REPOSITORY_KEY : _(' Repositories: %d\n'),
# NOTE_KEY : _(' Notes: %d\n'),
# TAG_KEY : _(' Tags: %d\n'),
# }
# txt = _("Number of new objects imported:\n")
# for key in self.keyorder:
# txt += key2string[key] % self.data_newobject[self.key2data[key]]
# InfoDialog(_('Upgrade Statistics'), infotxt, self.window)
# Example database from repository took:
# 3403 events upgraded with 8 citations in 23 seconds. Backlinks took 1071 seconds
# actually 4 of these citations were from:
# Media upgrade 4 citations upgraded in 4 seconds
# by only doing the backlinks when there might be something to do,
# improved to:
# 3403 events upgraded with 8 citations in 19 seconds. Backlinks took 1348 seconds
# further improved by skipping debug logging:
# 3403 events upgraded with 8 citations in 2 seconds. Backlinks took 167 seconds
# Bump up database version. Separate transaction to save metadata.
with BSDDBTxn(self.env, self.metadata) as txn:
txn.put('version', 16)
def upgrade_media_list_16(self, media_list, transaction):
new_media_list = []
for media in media_list:
(privacy, source_list, note_list, attribute_list, ref, rect) = media
new_citation_list = convert_source_list_to_citation_list_16(
self, source_list, transaction)
new_attribute_list = upgrade_attribute_list_16(
self, attribute_list, transaction)
new_media = (privacy, new_citation_list, note_list, new_attribute_list,
ref, rect)
new_media_list.append((new_media))
return new_media_list
def upgrade_attribute_list_16(self, attribute_list, transaction):
new_attribute_list = []
for attribute in attribute_list:
(privacy, source_list, note_list, the_type,
value) = attribute
new_citation_list = convert_source_list_to_citation_list_16(
self, source_list, transaction)
new_attribute = (privacy, new_citation_list, note_list,
the_type, value)
new_attribute_list.append((new_attribute))
return new_attribute_list
def convert_source_list_to_citation_list_16(self, source_list, transaction):
global num_citations
citation_list = []
for source in source_list:
(new_handle, new_citation) = \
convert_sourceref_to_citation_16(self, source)
with BSDDBTxn(self.env, self.citation_map) as txn:
txn.put(str(new_handle), new_citation)
new_citation_list.append((new_handle))
return new_citation_list
txn.put(str(new_handle), new_citation, txn=transaction)
num_citations += 1
# add backlinks for references from Citation to Source
LOG.debug(" update ref map citation %s" %
[new_handle,
self.get_citation_from_handle(new_handle) ])
with BSDDBTxn(self.env) as txn:
self.update_reference_map(
self.get_citation_from_handle(new_handle),
transaction,
txn.txn)
citation_list.append((new_handle))
return citation_list
def convert_sourceref_to_citation_16(self, source):
LOG.debug(" convert_sourceref_to_citation_16")
LOG.debug(" old sourceref %s" % [source])
(date, private, note_list, confidence, ref, page) = source
new_handle = self.create_id()
new_media_list = []
new_data_map = {}
new_change = time.time()
LOG.debug(" self %s" % [self])
# FIXME: I don't understand why I can't use find_next_citation_gramps_id.
# Attempting to use it fails. This seems to be because cid_trans
# is not initialised properly. However I don't understand how this
# is ever initialised.
# FIXME: self.cmap_index does not seem to be initialised, but
# again I don't see how it is initialised for
# find_next_citation_gramps_id
# FIXME: Should self.citation_map and/or cmap_index be committed to the
# database after being updated?
LOG.debug(" cmap_index %s" % self.cmap_index)
LOG.debug(" len(self.citation_map) %s" % len(self.citation_map))
(self.cmap_index, new_gramps_id) = \
__find_next_gramps_id(self, self.citation_prefix,
self.cmap_index)
LOG.debug(" new_gramps_id %s" % new_gramps_id)
new_citation = (new_handle, new_gramps_id,
date, page, confidence, ref, note_list, new_media_list,
new_data_map, new_change, private)
LOG.debug(" new_citation %s" % [new_citation])
return (new_handle, new_citation)
def __find_next_gramps_id(self, prefix, map_index):
"""

View File

@ -1875,7 +1875,15 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
if version < 15:
upgrade.gramps_upgrade_15(self)
if version < 16:
self.__connect_secondary()
# Open undo database
self.__open_undodb()
self.db_is_open = True
upgrade.gramps_upgrade_16(self)
# Close undo database
self.__close_undodb()
self.db_is_open = False
_LOG.debug("Upgrade time: %d seconds" % int(time.time()-t))

View File

@ -3,6 +3,7 @@
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2010 Michiel D. Nauta
# Copyright (C) 2011 Tim G L Lyons
#
# 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
@ -32,7 +33,7 @@ Attribute class for GRAMPS.
#-------------------------------------------------------------------------
from gen.lib.secondaryobj import SecondaryObject
from gen.lib.privacybase import PrivacyBase
from gen.lib.srcbase import SourceBase
from gen.lib.citationbase import CitationBase
from gen.lib.notebase import NoteBase
from gen.lib.attrtype import AttributeType
from gen.lib.const import IDENTICAL, EQUAL, DIFFERENT
@ -42,7 +43,7 @@ from gen.lib.const import IDENTICAL, EQUAL, DIFFERENT
# Attribute for Person/Family/MediaObject/MediaRef
#
#-------------------------------------------------------------------------
class Attribute(SecondaryObject, PrivacyBase, SourceBase, NoteBase):
class Attribute(SecondaryObject, PrivacyBase, CitationBase, NoteBase):
"""
Provide a simple key/value pair for describing properties.
Used to store descriptive information.
@ -63,7 +64,7 @@ class Attribute(SecondaryObject, PrivacyBase, SourceBase, NoteBase):
Create a new Attribute object, copying from the source if provided.
"""
PrivacyBase.__init__(self, source)
SourceBase.__init__(self, source)
CitationBase.__init__(self, source)
NoteBase.__init__(self, source)
if source:
@ -78,7 +79,7 @@ class Attribute(SecondaryObject, PrivacyBase, SourceBase, NoteBase):
Convert the object to a serialized tuple of data.
"""
return (PrivacyBase.serialize(self),
SourceBase.serialize(self),
CitationBase.serialize(self),
NoteBase.serialize(self),
self.type.serialize(), self.value)
@ -86,9 +87,9 @@ class Attribute(SecondaryObject, PrivacyBase, SourceBase, NoteBase):
"""
Convert a serialized tuple of data to an object.
"""
(privacy, source_list, note_list, the_type, self.value) = data
(privacy, citation_list, note_list, the_type, self.value) = data
PrivacyBase.unserialize(self, privacy)
SourceBase.unserialize(self, source_list)
CitationBase.unserialize(self, citation_list)
NoteBase.unserialize(self, note_list)
self.type.unserialize(the_type)
return self
@ -109,7 +110,7 @@ class Attribute(SecondaryObject, PrivacyBase, SourceBase, NoteBase):
:returns: Returns the list of child objects that may carry textual data.
:rtype: list
"""
return self.source_list
return []
def get_note_child_list(self):
"""
@ -119,7 +120,7 @@ class Attribute(SecondaryObject, PrivacyBase, SourceBase, NoteBase):
refer notes.
:rtype: list
"""
return self.source_list
return []
def get_handle_referents(self):
"""
@ -129,7 +130,7 @@ class Attribute(SecondaryObject, PrivacyBase, SourceBase, NoteBase):
:returns: Returns the list of objects referencing primary objects.
:rtype: list
"""
return self.source_list
return []
def get_referenced_handles(self):
"""
@ -139,7 +140,8 @@ class Attribute(SecondaryObject, PrivacyBase, SourceBase, NoteBase):
:returns: List of (classname, handle) tuples for referenced objects.
:rtype: list
"""
return self.get_referenced_note_handles()
return self.get_referenced_note_handles() + \
self.get_referenced_citation_handles()
def is_equivalent(self, other):
"""
@ -169,7 +171,7 @@ class Attribute(SecondaryObject, PrivacyBase, SourceBase, NoteBase):
:rtype acquisition: Attribute
"""
self._merge_privacy(acquisition)
self._merge_source_reference_list(acquisition)
self._merge_citation_list(acquisition)
self._merge_note_list(acquisition)
def set_type(self, val):

View File

@ -50,7 +50,13 @@ from gen.lib.const import DIFFERENT, EQUAL, IDENTICAL
#
#-------------------------------------------------------------------------
class Citation(MediaBase, NoteBase, PrimaryObject, RefBase, DateBase):
"""A record of a citation of a source of information."""
"""
A record of a citation of a source of information.
In GEDCOM this is called a SOURCE_CITATION.
The data provided in the <<SOURCE_CITATION>> structure is source-related
information specific to the data being cited.
"""
CONF_VERY_HIGH = 4
CONF_HIGH = 3
@ -121,12 +127,6 @@ class Citation(MediaBase, NoteBase, PrimaryObject, RefBase, DateBase):
this object type.
:rtype: bool
"""
# FIXME: it appears that this is only called for 'Event', 'Person',
# 'Place' and 'Repository', hence this is untested and may be
# unnecessary.
# FIXME: and libgrdb find_backlink_handles for all primary types
# should add 'Note', 'Media', 'Source'
if classname == 'Note':
return handle in [ref.ref for ref in self.note_list]
elif classname == 'Media':
@ -144,8 +144,9 @@ class Citation(MediaBase, NoteBase, PrimaryObject, RefBase, DateBase):
:param handle_list: The list of handles to be removed.
:type handle_list: str
"""
# FIXME: The following primary objects can refer to Citations:
# Person, Family, Event, MediaObject, Place
# FIXME: Citations can refer to Notes, MediaObjects and one Source.
# MediaObjects and dealt with in Primary object,
# Notes do not seem to be dealt with at all !!
if classname == 'Source' and \
self.get_reference_handle() in handle_list:
self.set_reference_handle(None)
@ -161,8 +162,9 @@ class Citation(MediaBase, NoteBase, PrimaryObject, RefBase, DateBase):
:param new_handle: The handle to replace the old one with.
:type new_handle: str
"""
# FIXME: The following primary objects can refer to Citations:
# Person, Family, Event, MediaObject, Place
# FIXME: Citations can refer to Notes, MediaObjects and one Source.
# MediaObjects and dealt with in Primary object,
# Notes do not seem to be dealt with at all !!
if classname == 'Source' and \
RefBase.get_reference_handle(self) == old_handle:
self.ref = RefBase.set_reference_handle(self, new_handle)
@ -186,20 +188,18 @@ class Citation(MediaBase, NoteBase, PrimaryObject, RefBase, DateBase):
:returns: Returns the list of child objects that may carry textual data.
:rtype: list
"""
# FIXME: Apparently does not include 'Note' child objects
return self.media_list
def get_sourcref_child_list(self):
"""
Return the list of child secondary objects that may refer sources.
:returns: Returns the list of child secondary child objects that may
refer sources.
:rtype: list
"""
# FIXME: should this also return the source reference child
# secondary object as this will refer to a Source Primary object
return self.media_list + self.ref
# def get_sourcref_child_list(self):
# # FIXME: I think we no longer need to handle source references
# """
# Return the list of child secondary objects that may refer sources.
#
# :returns: Returns the list of child secondary child objects that may
# refer sources.
# :rtype: list
# """
# return self.media_list + self.ref
def get_note_child_list(self):
"""
@ -209,9 +209,6 @@ class Citation(MediaBase, NoteBase, PrimaryObject, RefBase, DateBase):
refer notes.
:rtype: list
"""
# FIXME: should this also return the source reference child
# secondary object as this will refer to a Source Primary object
# that can itself refer to notes
return self.media_list
def get_handle_referents(self):
@ -222,9 +219,6 @@ class Citation(MediaBase, NoteBase, PrimaryObject, RefBase, DateBase):
:returns: Returns the list of objects referencing primary objects.
:rtype: list
"""
# FIXME: should this also return the source reference child
# secondary object as this will refer to a Primary objects,
# namely the Source object?
return self.media_list
def get_referenced_handles(self):
@ -235,54 +229,51 @@ class Citation(MediaBase, NoteBase, PrimaryObject, RefBase, DateBase):
:returns: List of (classname, handle) tuples for referenced objects.
:rtype: list
"""
# FIXME: Apparently this does not include 'Media'
ret = self.get_referenced_note_handles()
if self.ref:
ret += [('Source', self.ref)]
LOG.debug ("Citation: %s get_referenced_handles: %s" %
(self.page, ret))
return ret
def has_source_reference(self, src_handle) :
"""
Return True if any of the child objects has reference to this source
handle.
:param src_handle: The source handle to be checked.
:type src_handle: str
:returns: Returns whether any of it's child objects has reference to
this source handle.
:rtype: bool
"""
for item in self.get_sourcref_child_list():
if item.has_source_reference(src_handle):
return True
return False
def remove_source_references(self, src_handle_list):
"""
Remove references to all source handles in the list in all child
objects.
:param src_handle_list: The list of source handles to be removed.
:type src_handle_list: list
"""
for item in self.get_sourcref_child_list():
item.remove_source_references(src_handle_list)
def replace_source_references(self, old_handle, new_handle):
"""
Replace references to source_handles in the list in this object and
all child objects and merge equivalent entries.
:param old_handle: The source handle to be replaced.
:type old_handle: str
:param new_handle: The source handle to replace the old one with.
:type new_handle: str
"""
for item in self.get_sourcref_child_list():
item.replace_source_references(old_handle, new_handle)
# def has_source_reference(self, src_handle) :
# """
# Return True if any of the child objects has reference to this source
# handle.
#
# :param src_handle: The source handle to be checked.
# :type src_handle: str
# :returns: Returns whether any of it's child objects has reference to
# this source handle.
# :rtype: bool
# """
# for item in self.get_sourcref_child_list():
# if item.has_source_reference(src_handle):
# return True
#
# return False
#
# def remove_source_references(self, src_handle_list):
# """
# Remove references to all source handles in the list in all child
# objects.
#
# :param src_handle_list: The list of source handles to be removed.
# :type src_handle_list: list
# """
# for item in self.get_sourcref_child_list():
# item.remove_source_references(src_handle_list)
#
# def replace_source_references(self, old_handle, new_handle):
# """
# Replace references to source_handles in the list in this object and
# all child objects and merge equivalent entries.
#
# :param old_handle: The source handle to be replaced.
# :type old_handle: str
# :param new_handle: The source handle to replace the old one with.
# :type new_handle: str
# """
# for item in self.get_sourcref_child_list():
# item.replace_source_references(old_handle, new_handle)
def merge(self, acquisition):
"""

View File

@ -97,7 +97,7 @@ class CitationBase(object):
secondary child objects.
:param handle: :class:`~gen.lib.citation.Citation` handle to remove
from the list of citations
from the list of citations
:type handle: str
"""
LOG.debug('enter remove_citation handle %s' % handle)
@ -110,6 +110,16 @@ class CitationBase(object):
for item in self.get_citation_child_list():
item.remove_citation(handle)
def get_citation_references(self) :
"""
Return the list of citations associated with the object.
:returns: Returns the list of :class:`~gen.lib.Citation` handles
associated with the object.
:rtype: list
"""
return self.citation_list
def get_citation_child_list(self):
"""
Return the list of child secondary objects that may refer citations.

View File

@ -31,7 +31,7 @@ Event object for GRAMPS.
#
#-------------------------------------------------------------------------
from gen.lib.primaryobj import PrimaryObject
from gen.lib.srcbase import SourceBase
from gen.lib.citationbase import CitationBase
from gen.lib.notebase import NoteBase
from gen.lib.mediabase import MediaBase
from gen.lib.attrbase import AttributeBase
@ -44,7 +44,7 @@ from gen.lib.eventtype import EventType
# Event class
#
#-------------------------------------------------------------------------
class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
class Event(CitationBase, NoteBase, MediaBase, AttributeBase,
DateBase, PlaceBase, PrimaryObject):
"""
The Event record is used to store information about some type of
@ -67,7 +67,7 @@ class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
"""
PrimaryObject.__init__(self, source)
SourceBase.__init__(self, source)
CitationBase.__init__(self, source)
NoteBase.__init__(self, source)
MediaBase.__init__(self, source)
AttributeBase.__init__(self)
@ -102,7 +102,7 @@ class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
return (self.handle, self.gramps_id, self.__type.serialize(),
DateBase.serialize(self, no_text_date),
self.__description, self.place,
SourceBase.serialize(self),
CitationBase.serialize(self),
NoteBase.serialize(self),
MediaBase.serialize(self),
AttributeBase.serialize(self),
@ -119,7 +119,7 @@ class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
"""
(self.handle, self.gramps_id, the_type, date,
self.__description, self.place,
source_list, note_list, media_list, attribute_list,
citation_list, note_list, media_list, attribute_list,
self.change, self.private) = data
self.__type = EventType()
@ -127,7 +127,7 @@ class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
DateBase.unserialize(self, date)
MediaBase.unserialize(self, media_list)
AttributeBase.unserialize(self, attribute_list)
SourceBase.unserialize(self, source_list)
CitationBase.unserialize(self, citation_list)
NoteBase.unserialize(self, note_list)
def _has_handle_reference(self, classname, handle):
@ -189,14 +189,14 @@ class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
:returns: Returns the list of child objects that may carry textual data.
:rtype: list
"""
return self.media_list + self.source_list + self.attribute_list
return self.media_list + self.attribute_list
def get_sourcref_child_list(self):
def get_citationref_child_list(self):
"""
Return the list of child secondary objects that may refer sources.
Return the list of child secondary objects that may refer citations.
:returns: Returns the list of child secondary child objects that may
refer sources.
refer citations.
:rtype: list
"""
return self.media_list + self.attribute_list
@ -209,7 +209,7 @@ class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
refer notes.
:rtype: list
"""
return self.media_list + self.attribute_list + self.source_list
return self.media_list + self.attribute_list
def get_referenced_handles(self):
"""
@ -219,7 +219,8 @@ class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
:returns: List of (classname, handle) tuples for referenced objects.
:rtype: list
"""
ret = self.get_referenced_note_handles()
ret = self.get_referenced_note_handles() + \
self.get_referenced_citation_handles()
if self.place:
ret.append(('Place', self.place))
return ret
@ -232,7 +233,7 @@ class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
:returns: Returns the list of objects referencing primary objects.
:rtype: list
"""
return self.get_sourcref_child_list() + self.source_list
return self.get_citationref_child_list()
def is_empty(self):
"""
@ -265,12 +266,12 @@ class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
self.__description != other.__description \
or self.private != other.private or \
(not self.get_date_object().is_equal(other.get_date_object())) or \
len(self.get_source_references()) != len(other.get_source_references()):
len(self.get_citation_references()) != len(other.get_citation_references()):
return False
index = 0
olist = other.get_source_references()
for a in self.get_source_references():
olist = other.get_citation_references()
for a in self.get_citation_references():
if not a.is_equal(olist[index]):
return False
index += 1
@ -289,7 +290,7 @@ class Event(SourceBase, NoteBase, MediaBase, AttributeBase,
self._merge_privacy(acquisition)
self._merge_attribute_list(acquisition)
self._merge_note_list(acquisition)
self._merge_source_reference_list(acquisition)
self._merge_citation_list(acquisition)
self._merge_media_list(acquisition)
def set_type(self, the_type):

View File

@ -42,7 +42,6 @@ LOG = logging.getLogger(".citation")
#
#-------------------------------------------------------------------------
from gen.lib.primaryobj import PrimaryObject
from gen.lib.srcbase import SourceBase
from gen.lib.citationbase import CitationBase
from gen.lib.notebase import NoteBase
from gen.lib.datebase import DateBase
@ -54,7 +53,7 @@ from gen.lib.tagbase import TagBase
# MediaObject class
#
#-------------------------------------------------------------------------
class MediaObject(SourceBase, CitationBase, NoteBase, DateBase, AttributeBase,
class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
TagBase, PrimaryObject):
"""
Container for information about an image file, including location,
@ -72,12 +71,11 @@ class MediaObject(SourceBase, CitationBase, NoteBase, DateBase, AttributeBase,
:type source: MediaObject
"""
PrimaryObject.__init__(self, source)
SourceBase.__init__(self, source)
CitationBase.__init__(self, source)
NoteBase.__init__(self, source)
DateBase.__init__(self, source)
AttributeBase.__init__(self, source)
TagBase.__init__(self)
CitationBase.__init__(self)
if source:
self.path = source.path
@ -110,12 +108,11 @@ class MediaObject(SourceBase, CitationBase, NoteBase, DateBase, AttributeBase,
"""
return (self.handle, self.gramps_id, self.path, self.mime, self.desc,
AttributeBase.serialize(self),
SourceBase.serialize(self),
CitationBase.serialize(self),
NoteBase.serialize(self),
self.change,
DateBase.serialize(self, no_text_date),
TagBase.serialize(self),
CitationBase.serialize(self),
self.private)
def unserialize(self, data):
@ -127,17 +124,14 @@ class MediaObject(SourceBase, CitationBase, NoteBase, DateBase, AttributeBase,
:type data: tuple
"""
(self.handle, self.gramps_id, self.path, self.mime, self.desc,
attribute_list, source_list, note_list, self.change,
date, tag_list,
citation_list,
self.private) = data
attribute_list, citation_list, note_list, self.change,
date, tag_list, self.private) = data
AttributeBase.unserialize(self, attribute_list)
SourceBase.unserialize(self, source_list)
CitationBase.unserialize(self, citation_list)
NoteBase.unserialize(self, note_list)
DateBase.unserialize(self, date)
TagBase.unserialize(self, tag_list)
CitationBase.unserialize(self, citation_list)
def get_text_data_list(self):
"""
@ -157,27 +151,27 @@ class MediaObject(SourceBase, CitationBase, NoteBase, DateBase, AttributeBase,
"""
return self.attribute_list + self.source_list
def get_sourcref_child_list(self):
"""
Return the list of child secondary objects that may refer sources.
:returns: Returns the list of child secondary child objects that may
refer sources.
:rtype: list
"""
return self.attribute_list
# def get_sourcref_child_list(self):
# """
# Return the list of child secondary objects that may refer sources.
#
# :returns: Returns the list of child secondary child objects that may
# refer sources.
# :rtype: list
# """
# return self.attribute_list
#
def get_citation_child_list(self):
"""
Return the list of child secondary objects that may refer sources.
Return the list of child secondary objects that may refer to citations.
:returns: Returns the list of child secondary child objects that may
refer sources.
refer to citations.
:rtype: list
"""
# N.B. the citation_list of the media object is not a child object
# it is a direct reference from Media to a citation.
return []
return self.attribute_list
def get_note_child_list(self):
"""
@ -216,11 +210,11 @@ class MediaObject(SourceBase, CitationBase, NoteBase, DateBase, AttributeBase,
"""
LOG.debug ("Media: %s get_handle_referents: %s" %
(self.desc,
self.attribute_list + self.source_list))
self.attribute_list))
# FIXME: This is wrong, because it returns the handle, when it should return
# the citation object. This is probably because the citation unpack has not
# been done.
return self.attribute_list + self.source_list
return self.attribute_list
def merge(self, acquisition):
"""
@ -234,7 +228,7 @@ class MediaObject(SourceBase, CitationBase, NoteBase, DateBase, AttributeBase,
self._merge_privacy(acquisition)
self._merge_attribute_list(acquisition)
self._merge_note_list(acquisition)
self._merge_source_reference_list(acquisition)
self._merge_citation_list(acquisition)
self._merge_tag_list(acquisition)
self.merge_citation_list(acquisition)

View File

@ -32,7 +32,7 @@ Media Reference class for GRAMPS.
#-------------------------------------------------------------------------
from gen.lib.secondaryobj import SecondaryObject
from gen.lib.privacybase import PrivacyBase
from gen.lib.srcbase import SourceBase
from gen.lib.citationbase import CitationBase
from gen.lib.notebase import NoteBase
from gen.lib.refbase import RefBase
from gen.lib.attrbase import AttributeBase
@ -43,12 +43,12 @@ from gen.lib.const import IDENTICAL, EQUAL, DIFFERENT
# MediaObject References for Person/Place/Source
#
#-------------------------------------------------------------------------
class MediaRef(SecondaryObject, PrivacyBase, SourceBase, NoteBase, RefBase,
class MediaRef(SecondaryObject, PrivacyBase, CitationBase, NoteBase, RefBase,
AttributeBase):
"""Media reference class."""
def __init__(self, source=None):
PrivacyBase.__init__(self, source)
SourceBase.__init__(self, source)
CitationBase.__init__(self, source)
NoteBase.__init__(self, source)
RefBase.__init__(self, source)
AttributeBase.__init__(self, source)
@ -63,7 +63,7 @@ class MediaRef(SecondaryObject, PrivacyBase, SourceBase, NoteBase, RefBase,
Convert the object to a serialized tuple of data.
"""
return (PrivacyBase.serialize(self),
SourceBase.serialize(self),
CitationBase.serialize(self),
NoteBase.serialize(self),
AttributeBase.serialize(self),
RefBase.serialize(self),
@ -73,9 +73,9 @@ class MediaRef(SecondaryObject, PrivacyBase, SourceBase, NoteBase, RefBase,
"""
Convert a serialized tuple of data to an object.
"""
(privacy, source_list, note_list,attribute_list,ref,self.rect) = data
(privacy, citation_list, note_list,attribute_list,ref,self.rect) = data
PrivacyBase.unserialize(self, privacy)
SourceBase.unserialize(self, source_list)
CitationBase.unserialize(self, citation_list)
NoteBase.unserialize(self, note_list)
AttributeBase.unserialize(self, attribute_list)
RefBase.unserialize(self, ref)
@ -88,14 +88,14 @@ class MediaRef(SecondaryObject, PrivacyBase, SourceBase, NoteBase, RefBase,
:returns: Returns the list of child objects that may carry textual data.
:rtype: list
"""
return self.attribute_list + self.source_list
return self.attribute_list # + self.source_list
def get_sourcref_child_list(self):
def get_citation_child_list(self):
"""
Return the list of child secondary objects that may refer sources.
Return the list of child secondary objects that may refer Citations.
:returns: Returns the list of child secondary child objects that may
refer sources.
refer Citations.
:rtype: list
"""
return self.attribute_list
@ -108,7 +108,7 @@ class MediaRef(SecondaryObject, PrivacyBase, SourceBase, NoteBase, RefBase,
refer notes.
:rtype: list
"""
return self.attribute_list + self.source_list
return self.attribute_list # + self.source_list
def get_referenced_handles(self):
"""
@ -118,7 +118,8 @@ class MediaRef(SecondaryObject, PrivacyBase, SourceBase, NoteBase, RefBase,
:returns: List of (classname, handle) tuples for referenced objects.
:rtype: list
"""
ret = self.get_referenced_note_handles()
ret = self.get_referenced_note_handles() + \
self.get_referenced_citation_handles()
if self.ref:
ret += [('MediaObject', self.ref)]
return ret
@ -131,7 +132,7 @@ class MediaRef(SecondaryObject, PrivacyBase, SourceBase, NoteBase, RefBase,
:returns: Returns the list of objects referencing primary objects.
:rtype: list
"""
return self.attribute_list + self.source_list
return self.attribute_list # + self.source_list
def is_equivalent(self, other):
"""
@ -162,7 +163,7 @@ class MediaRef(SecondaryObject, PrivacyBase, SourceBase, NoteBase, RefBase,
"""
self._merge_privacy(acquisition)
self._merge_attribute_list(acquisition)
self._merge_source_reference_list(acquisition)
self._merge_citation_list(acquisition)
self._merge_note_list(acquisition)
def set_rectangle(self, coord):

View File

@ -48,7 +48,7 @@ import gtk
from editsecondary import EditSecondary
from gen.lib import NoteType
from glade import Glade
from displaytabs import SourceEmbedList, NoteTab
from displaytabs import CitationEmbedList, NoteTab
from gui.widgets import MonitoredEntry, PrivacyButton, MonitoredDataType
#-------------------------------------------------------------------------
@ -107,7 +107,10 @@ class EditAttribute(EditSecondary):
def _create_tabbed_pages(self):
notebook = gtk.Notebook()
self.srcref_list = SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj)
self.srcref_list = CitationEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj.get_citation_list())
self._add_tab(notebook, self.srcref_list)
self.track_ref_for_deletion("srcref_list")

View File

@ -110,9 +110,8 @@ class EditCitation(EditPrimary):
title = _('New Citation')
return title
# FIXME: There will have to be two warnings,
# one because Source may be shared and one because Citation may be shared.
# These three functions are normally inherited from editreference,
# The functions define_warn_box, enable_warn_box and define_expander
# are normally inherited from editreference,
# but have to be defined here because this class inherits from
# EditPrimary instead
def define_warn_box(self,box):
@ -121,6 +120,12 @@ class EditCitation(EditPrimary):
def enable_warnbox(self):
self.warn_box.show()
def define_warn_box2(self,box):
self.warn_box2 = box
def enable_warnbox2(self):
self.warn_box2.show()
def define_expander(self,expander):
expander.set_expanded(True)
@ -141,6 +146,7 @@ class EditCitation(EditPrimary):
self.get_menu_title())
self.define_warn_box(self.glade.get_object("warn_box"))
self.define_warn_box2(self.glade.get_object("warn_box2"))
self.define_expander(self.glade.get_object("src_expander"))
tblref = self.glade.get_object('table67')
@ -266,11 +272,10 @@ class EditCitation(EditPrimary):
self._add_tab(notebook_ref, self.data_tab)
self.track_ref_for_deletion("data_tab")
# FIXME: This needs to enable the shared Citation warning box
self.citationref_list = SourceBackRefList(self.dbstate,self.uistate,
self.citationref_list = SourceBackRefList(self.dbstate, self.uistate,
self.track,
self.db.find_backlink_handles(self.obj.handle),
self.enable_warnbox)
self.enable_warnbox2)
self._add_tab(notebook_ref, self.citationref_list)
self.track_ref_for_deletion("citationref_list")

View File

@ -48,7 +48,7 @@ from editprimary import EditPrimary
from objectentries import PlaceEntry
from glade import Glade
from QuestionDialog import ErrorDialog
from displaytabs import (SourceEmbedList, NoteTab, GalleryTab,
from displaytabs import (CitationEmbedList, NoteTab, GalleryTab,
EventBackRefList, AttrEmbedList)
from gui.widgets import (MonitoredEntry, PrivacyButton,
MonitoredDataType, MonitoredDate)
@ -172,11 +172,12 @@ class EditEvent(EditPrimary):
"""
notebook = gtk.Notebook()
self.source_list = SourceEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj)
self._add_tab(notebook, self.source_list)
self.citation_list = CitationEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj.get_citation_list(),
self.get_menu_title())
self._add_tab(notebook, self.citation_list)
self.note_list = NoteTab(self.dbstate,
self.uistate,
@ -210,7 +211,7 @@ class EditEvent(EditPrimary):
notebook.show_all()
self.top.get_object('vbox').pack_start(notebook, True)
self.track_ref_for_deletion("source_list")
self.track_ref_for_deletion("citation_list")
self.track_ref_for_deletion("note_list")
self.track_ref_for_deletion("gallery_list")
self.track_ref_for_deletion("attr_list")

View File

@ -36,7 +36,7 @@ from gen.ggettext import gettext as _
import gen.lib
from gen.db import DbTxn
from glade import Glade
from displaytabs import (SourceEmbedList, NoteTab, GalleryTab,
from displaytabs import (CitationEmbedList, NoteTab, GalleryTab,
EventBackRefList, AttrEmbedList)
from gui.widgets import (PrivacyButton, MonitoredEntry,
MonitoredDate, MonitoredDataType)
@ -172,10 +172,10 @@ class EditEventRef(EditReference):
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.srcref_list = CitationEmbedList(self.dbstate,
self.uistate,
self.track,
self.source.get_citation_list())
self._add_tab(notebook, self.srcref_list)
self.track_ref_for_deletion("srcref_list")

View File

@ -192,13 +192,14 @@ class EditMedia(EditPrimary):
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.citation_tab = CitationEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj.get_citation_list(),
self.get_menu_title())
self._add_tab(notebook, self.citation_tab)
self.track_ref_for_deletion("citation_tab")
self.attr_tab = AttrEmbedList(self.dbstate,
self.uistate,
self.track,
@ -214,14 +215,6 @@ class EditMedia(EditPrimary):
self._add_tab(notebook, self.note_tab)
self.track_ref_for_deletion("note_tab")
self.citation_tab = CitationEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj.get_citation_list(),
self.get_menu_title())
self._add_tab(notebook, self.citation_tab)
self.track_ref_for_deletion("citation_tab")
self.backref_tab = MediaBackRefList(self.dbstate,
self.uistate,
self.track,

View File

@ -49,7 +49,7 @@ import Utils
from gen.lib import NoteType
from gen.db import DbTxn
from glade import Glade
from displaytabs import (SourceEmbedList, AttrEmbedList, MediaBackRefList,
from displaytabs import (CitationEmbedList, AttrEmbedList, MediaBackRefList,
NoteTab)
from gui.widgets import MonitoredSpinButton, MonitoredEntry, PrivacyButton
from editreference import RefTab, EditReference
@ -543,8 +543,10 @@ class EditMediaRef(EditReference):
self._add_tab(notebook_src, self.primtab)
self._add_tab(notebook_ref, self.reftab)
self.srcref_list = SourceEmbedList(self.dbstate,self.uistate,self.track,
self.source_ref)
self.srcref_list = CitationEmbedList(self.dbstate,
self.uistate,
self.track,
self.source_ref.get_citation_list())
self._add_tab(notebook_ref, self.srcref_list)
self.track_ref_for_deletion("srcref_list")
@ -566,8 +568,10 @@ class EditMediaRef(EditReference):
self._add_tab(notebook_ref, self.note_ref_tab)
self.track_ref_for_deletion("note_ref_tab")
self.src_srcref_list = SourceEmbedList(self.dbstate,self.uistate,
self.track, self.source)
self.src_srcref_list = CitationEmbedList(self.dbstate,
self.uistate,
self.track,
self.source.get_citation_list())
self._add_tab(notebook_src, self.src_srcref_list)
self.track_ref_for_deletion("src_srcref_list")

View File

@ -49,7 +49,7 @@ from gen.db import DbTxn
from editprimary import EditPrimary
from displaytabs import (NoteTab, GalleryTab, DataEmbedList,
SourceBackRefList, RepoEmbedList)
CitationBackRefList, RepoEmbedList)
from gui.widgets import MonitoredEntry, PrivacyButton
from QuestionDialog import ErrorDialog
from glade import Glade
@ -160,7 +160,7 @@ class EditSource(EditPrimary):
self._add_tab(notebook, self.repo_tab)
self.track_ref_for_deletion("repo_tab")
self.backref_list = SourceBackRefList(self.dbstate,
self.backref_list = CitationBackRefList(self.dbstate,
self.uistate,
self.track,
self.db.find_backlink_handles(self.obj.handle))

View File

@ -36,6 +36,7 @@ import time
import logging
_LOG = logging.getLogger('.gui.listview')
LOG = logging.getLogger(".citation")
#----------------------------------------------------------------
#

View File

@ -0,0 +1,469 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2011 Tim G L Lyons
#
# 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$
#
from gui.editors import EditCitation
from ListModel import ListModel, NOSORT
from gen.plug import Gramplet
from gen.ggettext import gettext as _
import Errors
import gtk
class Citations(Gramplet):
"""
Displays the citations for an object.
"""
def init(self):
self.gui.WIDGET = self.build_gui()
self.gui.get_container_widget().remove(self.gui.textview)
self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET)
self.gui.WIDGET.show()
def build_gui(self):
"""
Build the GUI interface.
"""
tip = _('Double-click on a row to edit the selected citation.')
self.set_tooltip(tip)
top = gtk.TreeView()
titles = [('', NOSORT, 50,),
(_('Source'), 1, 200),
(_('Reference'), 2, 300),
(_('Author'), 3, 100)]
self.model = ListModel(top, titles, event_func=self.edit_citation)
return top
def add_citations(self, obj):
for citation_handle in obj.get_citation_references():
self.add_citation_ref(citation_handle)
def add_name_citations(self, obj):
names = [obj.get_primary_name()] + obj.get_alternate_names()
for name in names:
self.add_citations(name)
def add_attribute_citations(self, obj):
for attr in obj.get_attribute_list():
self.add_citations(attr)
def add_mediaref_citations(self, obj):
for media_ref in obj.get_media_list():
self.add_citations(media_ref)
self.add_attribute_citations(media_ref)
media = self.dbstate.db.get_object_from_handle(media_ref.ref)
self.add_media_citations(media)
def add_media_citations(self, media):
self.add_citations(media)
self.add_attribute_citations(media)
def add_eventref_citations(self, obj):
for event_ref in obj.get_event_ref_list():
self.add_attribute_citations(event_ref)
event = self.dbstate.db.get_event_from_handle(event_ref.ref)
self.add_event_citations(event)
def add_event_citations(self, event):
self.add_citations(event)
self.add_attribute_citations(event)
self.add_mediaref_citations(event)
place_handle = event.get_place_handle()
place = self.dbstate.db.get_place_from_handle(place_handle)
if place:
self.add_place_citations(place)
def add_place_citations(self, place):
self.add_citations(place)
self.add_mediaref_citations(place)
def add_address_citations(self, obj):
for address in obj.get_address_list():
self.add_citations(address)
def add_lds_citations(self, obj):
for lds in obj.get_lds_ord_list():
self.add_citations(lds)
place_handle = lds.get_place_handle()
place = self.dbstate.db.get_place_from_handle(place_handle)
if place:
self.add_place_citations(place)
def add_association_citations(self, obj):
for assoc in obj.get_person_ref_list():
self.add_citations(assoc)
def add_citation_ref(self, citation_handle):
"""
Add a citation to the model.
"""
citation = self.dbstate.db.get_citation_from_handle(citation_handle)
page = citation.get_page()
source = self.dbstate.db.get_source_from_handle(citation.ref)
title = source.get_title()
author = source.get_author()
self.model.add((citation_handle, title, page, author))
def check_citations(self, obj):
return True if obj.get_citation_references() else False
def check_name_citations(self, obj):
names = [obj.get_primary_name()] + obj.get_alternate_names()
for name in names:
if self.check_citations(name):
return True
return False
def check_attribute_citations(self, obj):
for attr in obj.get_attribute_list():
if self.check_citations(attr):
return True
return False
def check_mediaref_citations(self, obj):
for media_ref in obj.get_media_list():
if self.check_citations(media_ref):
return True
if self.check_attribute_citations(media_ref):
return True
media = self.dbstate.db.get_object_from_handle(media_ref.ref)
if self.check_media_citations(media):
return True
return False
def check_media_citations(self, media):
if self.check_citations(media):
return True
if self.check_attribute_citations(media):
return True
return False
def check_eventref_citations(self, obj):
for event_ref in obj.get_event_ref_list():
if self.check_attribute_citations(event_ref):
return True
event = self.dbstate.db.get_event_from_handle(event_ref.ref)
if self.check_event_citations(event):
return True
return False
def check_event_citations(self, event):
if self.check_citations(event):
return True
if self.check_attribute_citations(event):
return True
if self.check_mediaref_citations(event):
return True
place_handle = event.get_place_handle()
place = self.dbstate.db.get_place_from_handle(place_handle)
if place and self.check_place_citations(place):
return True
return False
def check_place_citations(self, place):
if self.check_citations(place):
return True
if self.check_mediaref_citations(place):
return True
return False
def check_address_citations(self, obj):
for address in obj.get_address_list():
if self.check_citations(address):
return True
return False
def check_lds_citations(self, obj):
for lds in obj.get_lds_ord_list():
if self.check_citations(lds):
return True
place_handle = lds.get_place_handle()
place = self.dbstate.db.get_place_from_handle(place_handle)
if place and self.check_place_citations(place):
return True
return False
def check_association_citations(self, obj):
for assoc in obj.get_person_ref_list():
if self.check_citations(assoc):
return True
return False
def edit_citation(self, treeview):
"""
Edit the selected citation.
"""
model, iter_ = treeview.get_selection().get_selected()
if iter_:
handle = model.get_value(iter_, 0)
try:
citation = self.dbstate.db.get_citation_from_handle(handle)
source = self.dbstate.db.get_source_from_handle(citation.ref)
EditCitation(self.dbstate, self.uistate, [], citation, source)
except Errors.WindowActiveError:
pass
class PersonCitations(Citations):
"""
Displays the citations for a person.
"""
def db_changed(self):
self.dbstate.db.connect('person-update', self.update)
self.update()
def active_changed(self, handle):
self.update()
def update_has_data(self):
active_handle = self.get_active('Person')
active = self.dbstate.db.get_person_from_handle(active_handle)
self.set_has_data(self.get_has_data(active))
def main(self):
active_handle = self.get_active('Person')
active = self.dbstate.db.get_person_from_handle(active_handle)
self.model.clear()
if active:
self.display_citations(active)
else:
self.set_has_data(False)
def display_citations(self, person):
"""
Display the citations for the active person.
"""
self.add_citations(person)
self.add_eventref_citations(person)
for handle in person.get_family_handle_list():
family = self.dbstate.db.get_family_from_handle(handle)
self.add_eventref_citations(family)
self.add_name_citations(person)
self.add_attribute_citations(person)
self.add_address_citations(person)
self.add_mediaref_citations(person)
self.add_association_citations(person)
self.add_lds_citations(person)
self.set_has_data(self.model.count > 0)
def get_has_data(self, person):
"""
Return True if the gramplet has data, else return False.
"""
if person is None:
return False
if self.check_citations(person):
return True
if self.check_eventref_citations(person):
return True
for handle in person.get_family_handle_list():
family = self.dbstate.db.get_family_from_handle(handle)
if self.check_eventref_citations(family):
return True
if self.check_name_citations(person):
return True
if self.check_attribute_citations(person):
return True
if self.check_address_citations(person):
return True
if self.check_mediaref_citations(person):
return True
if self.check_association_citations(person):
return True
if self.check_lds_citations(person):
return True
return False
class EventCitations(Citations):
"""
Displays the citations for an event.
"""
def db_changed(self):
self.dbstate.db.connect('event-update', self.update)
self.connect_signal('Event', self.update)
self.update()
def update_has_data(self):
active_handle = self.get_active('Event')
active = self.dbstate.db.get_event_from_handle(active_handle)
self.set_has_data(self.get_has_data(active))
def main(self):
active_handle = self.get_active('Event')
active = self.dbstate.db.get_event_from_handle(active_handle)
self.model.clear()
if active:
self.display_citations(active)
else:
self.set_has_data(False)
def display_citations(self, event):
"""
Display the citations for the active event.
"""
self.add_event_citations(event)
self.set_has_data(self.model.count > 0)
def get_has_data(self, event):
"""
Return True if the gramplet has data, else return False.
"""
if event is None:
return False
if self.check_event_citations(event):
return True
return False
class FamilyCitations(Citations):
"""
Displays the citations for a family.
"""
def db_changed(self):
self.dbstate.db.connect('family-update', self.update)
self.connect_signal('Family', self.update)
self.update()
def update_has_data(self):
active_handle = self.get_active('Family')
active = self.dbstate.db.get_family_from_handle(active_handle)
self.set_has_data(self.get_has_data(active))
def main(self):
active_handle = self.get_active('Family')
active = self.dbstate.db.get_family_from_handle(active_handle)
self.model.clear()
if active:
self.display_citations(active)
else:
self.set_has_data(False)
def display_citations(self, family):
"""
Display the citations for the active family.
"""
self.add_citations(family)
self.add_eventref_citations(family)
self.add_attribute_citations(family)
self.add_mediaref_citations(family)
self.add_lds_citations(family)
self.set_has_data(self.model.count > 0)
def get_has_data(self, family):
"""
Return True if the gramplet has data, else return False.
"""
if family is None:
return False
if self.check_citations(family):
return True
if self.check_eventref_citations(family):
return True
if self.check_attribute_citations(family):
return True
if self.check_mediaref_citations(family):
return True
if self.check_lds_citations(family):
return True
return False
class PlaceCitations(Citations):
"""
Displays the citations for a place.
"""
def db_changed(self):
self.dbstate.db.connect('place-update', self.update)
self.connect_signal('Place', self.update)
self.update()
def update_has_data(self):
active_handle = self.get_active('Place')
active = self.dbstate.db.get_place_from_handle(active_handle)
self.set_has_data(self.get_has_data(active))
def main(self):
active_handle = self.get_active('Place')
active = self.dbstate.db.get_place_from_handle(active_handle)
self.model.clear()
if active:
self.display_citations(active)
else:
self.set_has_data(False)
def display_citations(self, place):
"""
Display the citations for the active place.
"""
self.add_place_citations(place)
self.set_has_data(self.model.count > 0)
def get_has_data(self, place):
"""
Return True if the gramplet has data, else return False.
"""
if place is None:
return False
if self.check_place_citations(place):
return True
return False
class MediaCitations(Citations):
"""
Displays the citations for a media object.
"""
def db_changed(self):
self.dbstate.db.connect('media-update', self.update)
self.connect_signal('Media', self.update)
self.update()
def update_has_data(self):
active_handle = self.get_active('Media')
active = self.dbstate.db.get_object_from_handle(active_handle)
self.set_has_data(self.get_has_data(active))
def main(self):
active_handle = self.get_active('Media')
active = self.dbstate.db.get_object_from_handle(active_handle)
self.model.clear()
if active:
self.display_citations(active)
else:
self.set_has_data(False)
def display_citations(self, media):
"""
Display the citations for the active media object.
"""
self.add_media_citations(media)
self.set_has_data(self.model.count > 0)
def get_has_data(self, media):
"""
Return True if the gramplet has data, else return False.
"""
if media is None:
return False
if self.check_media_citations(media):
return True
return False

View File

@ -14,6 +14,7 @@ pkgdata_PYTHON = \
bottombar.gpr.py \
CalendarGramplet.py \
Children.py \
Citations.py \
DescendGramplet.py \
EditExifMetadata.py \
Events.py \

View File

@ -0,0 +1,41 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 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$
#------------------------------------------------------------------------
#
# Register Gramplet
#
#------------------------------------------------------------------------
register(GRAMPLET,
id="Populate",
name=_("Populate data"),
description = _("Gramplet to populate database"),
version="2.0.0",
gramps_target_version="3.4",
status = STABLE,
fname="PopulateGramplet.py",
height=200,
gramplet = 'PopulateGramplet',
gramplet_title=_("Populate data"),
)

View File

@ -0,0 +1,128 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2011 Tim G L Lyons
#
# 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$
"""
Gramplet that populates the database with sources and citations.
"""
#------------------------------------------------------------------------
#
# Python modules
#
#------------------------------------------------------------------------
import logging
LOG = logging.getLogger(".citation")
#------------------------------------------------------------------------
#
# GRAMPS modules
#
#------------------------------------------------------------------------
from gen.plug import Gramplet
from gen.ggettext import sgettext as _
import DateHandler
from QuickReports import run_quick_report_by_name
import gen.lib
from gen.db import DbTxn
#------------------------------------------------------------------------
#
# Gramplet class
#
#------------------------------------------------------------------------
class PopulateGramplet(Gramplet):
"""
Gramplet that populates the database with sources and citations.
"""
def init(self):
"""
Constructs the GUI, consisting of a message, an entry, and
a Run button.
"""
import gtk
# GUI setup:
self.set_tooltip(_("Enter a date, click Run"))
vbox = gtk.VBox()
hbox = gtk.HBox()
# label, entry
description = gtk.TextView()
description.set_wrap_mode(gtk.WRAP_WORD)
description.set_editable(False)
buffer = description.get_buffer()
buffer.set_text(_("Enter a valid number of sources and citations."
" This will create the requested number of sources,"
" and for each source, will create the requested"
" number of citations."))
label_sources = gtk.Label()
label_sources.set_text(_("Number of sources") + ":")
self.num_sources = gtk.Entry()
label_citations = gtk.Label()
label_citations.set_text(_("Number of citations") + ":")
self.num_citations = gtk.Entry()
button = gtk.Button(_("Run"))
button.connect("clicked", self.run)
##self.filter =
hbox.pack_start(label_sources, False)
hbox.pack_start(self.num_sources, True)
hbox.pack_start(label_citations, False)
hbox.pack_start(self.num_citations, True)
vbox.pack_start(description, True)
vbox.pack_start(hbox, False)
vbox.pack_start(button, False)
self.gui.get_container_widget().remove(self.gui.textview)
self.gui.get_container_widget().add_with_viewport(vbox)
vbox.show_all()
def post_init(self):
self.disconnect("active-changed")
def run(self, obj):
"""
Method that is run when you click the Run button.
The date is retrieved from the entry box, parsed as a date,
and then handed to the quick report.
"""
num_sources_text = self.num_sources.get_text()
num_sources = int(num_sources_text)
num_citations_text = self.num_citations.get_text()
num_citations = int(num_citations_text)
LOG.debug("sources %04d citations %04d" % (num_sources,
num_citations))
source = gen.lib.Source()
citation = gen.lib.Citation()
db = self.gui.dbstate.db
for i in range(num_sources):
source.gramps_id = None
source.handle = None
source.title = "Source %04d" % i
with DbTxn('savesource', db) as trans:
db.add_source(source, trans)
for j in range(num_citations):
citation.gramps_id = None
citation.handle = None
citation.ref = source.handle
citation.page = "Page %04d" % j
with DbTxn('savecitation', db) as trans:
db.add_citation(citation, trans)

View File

@ -470,6 +470,76 @@ register(GRAMPLET,
navtypes=["Media"],
)
register(GRAMPLET,
id="Person Citations",
name=_("Person Citations"),
description = _("Gramplet showing the citations for a person"),
version="1.0.0",
gramps_target_version="3.4",
status = STABLE,
fname="Citations.py",
height=200,
gramplet = 'PersonCitations',
gramplet_title=_("Citations"),
navtypes=["Person"],
)
register(GRAMPLET,
id="Event Citations",
name=_("Event Citations"),
description = _("Gramplet showing the citations for an event"),
version="1.0.0",
gramps_target_version="3.4",
status = STABLE,
fname="Citations.py",
height=200,
gramplet = 'EventCitations',
gramplet_title=_("Citations"),
navtypes=["Event"],
)
register(GRAMPLET,
id="Family Citations",
name=_("Family Citations"),
description = _("Gramplet showing the citations for a family"),
version="1.0.0",
gramps_target_version="3.4",
status = STABLE,
fname="Citations.py",
height=200,
gramplet = 'FamilyCitations',
gramplet_title=_("Citations"),
navtypes=["Family"],
)
register(GRAMPLET,
id="Place Citations",
name=_("Place Citations"),
description = _("Gramplet showing the citations for a place"),
version="1.0.0",
gramps_target_version="3.4",
status = STABLE,
fname="Citations.py",
height=200,
gramplet = 'PlaceCitations',
gramplet_title=_("Citations"),
navtypes=["Place"],
)
register(GRAMPLET,
id="Media Citations",
name=_("Media Citations"),
description = _("Gramplet showing the citations for a media object"),
version="1.0.0",
gramps_target_version="3.4",
status = STABLE,
fname="Citations.py",
height=200,
gramplet = 'MediaCitations',
gramplet_title=_("Citations"),
navtypes=["Media"],
)
register(GRAMPLET,
id="Person Children",
name=_("Person Children"),

View File

@ -52,7 +52,7 @@ import Errors
from DdTargets import DdTargets
from gui.selectors import SelectorFactory
from QuestionDialog import ErrorDialog
from gui.editors import EditCitation, DeleteCitationQuery
from gui.editors import EditCitation, DeleteCitationQuery, EditSource
from Filters.SideBar import SourceSidebarFilter
from gen.plug import CATEGORY_QR_SOURCE
@ -238,6 +238,9 @@ class BaseCitationView(ListView):
pass
def add(self, obj):
"""
Add a new Citation to a user selected source
"""
SelectSource = SelectorFactory('Source')
sel = SelectSource(self.dbstate, self.uistate)
source = sel.run()
@ -250,38 +253,6 @@ class BaseCitationView(ListView):
WarningDialog(_("Cannot share this reference"),
self.__blocked_text())
def remove(self, obj):
self.remove_selected_objects()
def remove_object_from_handle(self, handle):
the_lists = Utils.get_citation_referents(handle, self.dbstate.db)
object = self.dbstate.db.get_citation_from_handle(handle)
query = DeleteCitationQuery(self.dbstate, self.uistate, object,
the_lists)
is_used = any(the_lists)
return (query, is_used, object)
def edit(self, obj):
for handle in self.selected_handles():
citation = self.dbstate.db.get_citation_from_handle(handle)
try:
source = self.dbstate.db.get_source_from_handle(citation.ref)
EditCitation(self.dbstate, self.uistate, [], citation, source)
except Errors.WindowActiveError:
pass
except:
LOG.warn("failed to find a Source for the selected Citation")
def __blocked_text(self):
"""
Return the common text used when mediaref cannot be edited
"""
return _("This media reference cannot be edited at this time. "
"Either the associated media object is already being "
"edited or another media reference that is associated with "
"the same media object is being edited.\n\nTo edit this "
"media reference, you need to close the media object.")
# def share(self, obj):
# SelectSource = SelectorFactory('Source')
# sel = SelectSource(self.dbstate,self.uistate)
@ -295,6 +266,48 @@ class BaseCitationView(ListView):
# WarningDialog(_("Cannot share this reference"),
# self.__blocked_text())
#
def remove(self, obj):
self.remove_selected_objects()
def remove_object_from_handle(self, handle):
the_lists = Utils.get_citation_referents(handle, self.dbstate.db)
object = self.dbstate.db.get_citation_from_handle(handle)
query = DeleteCitationQuery(self.dbstate, self.uistate, object,
the_lists)
is_used = any(the_lists)
return (query, is_used, object)
def edit(self, obj):
"""
Edit either a Source or a Citation, depending on user selection
"""
for handle in self.selected_handles():
# The handle will either be a Source handle or a Citation handle
citation = self.dbstate.db.get_citation_from_handle(handle)
if citation:
LOG.debug("citation handle %s page %s" %
(handle, citation.page))
source = self.dbstate.db.get_source_from_handle(citation.ref)
try:
EditCitation(self.dbstate, self.uistate, [], citation, source)
except Errors.WindowActiveError:
pass
else:
source = self.dbstate.db.get_source_from_handle(handle)
LOG.debug("source handle %s title %s " %
(source, source.title))
EditSource(self.dbstate, self.uistate, [], source)
def __blocked_text(self):
"""
Return the common text used when mediaref cannot be edited
"""
return _("This media reference cannot be edited at this time. "
"Either the associated media object is already being "
"edited or another media reference that is associated with "
"the same media object is being edited.\n\nTo edit this "
"media reference, you need to close the media object.")
def merge(self, obj):
"""
Merge the selected citations.

View File

@ -291,7 +291,7 @@ class EventView(ListView):
"""
return (("Event Filter",),
("Event Gallery",
"Event Sources",
"Event Citations",
"Event Notes",
"Event Attributes",
"Event Backlinks"))

View File

@ -425,7 +425,7 @@ class MediaView(ListView):
"""
return (("Media Filter",),
("Media Preview",
"Media Sources",
"Media Citations"
"Media Notes",
"Media Attributes",
"Metadata Viewer",