Simplify citation editor and add source selection

This commit is contained in:
Nick Hall 2014-03-02 19:12:50 +00:00
parent efd8a5bef6
commit 8241953765
4 changed files with 405 additions and 854 deletions

View File

@ -3,7 +3,8 @@
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2009 Gary Burton
# Copyright (C) 2011 Tim G L Lyons, Nick Hall
# Copyright (C) 2011 Tim G L Lyons
# Copyright (C) 2011,2014 Nick Hall
#
# 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
@ -20,10 +21,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
EditCitation class for GRAMPS.
EditCitation class for Gramps.
"""
#-------------------------------------------------------------------------
@ -36,6 +35,13 @@ _ = glocale.translation.gettext
import logging
LOG = logging.getLogger(".citation")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
from gi.repository import Gtk
#-------------------------------------------------------------------------
#
# gramps modules
@ -44,13 +50,11 @@ LOG = logging.getLogger(".citation")
from gramps.gen.lib import Citation, NoteType, Source
from gramps.gen.db import DbTxn
from .editprimary import EditPrimary
from .displaytabs import (NoteTab, GalleryTab, DataEmbedList,
SourceBackRefList, RepoEmbedList, CitationBackRefList)
from .objectentries import SourceEntry
from .displaytabs import NoteTab, GalleryTab, DataEmbedList, CitationBackRefList
from ..widgets import (MonitoredEntry, PrivacyButton, MonitoredMenu,
MonitoredDate)
MonitoredDate)
from ..dialog import ErrorDialog
from .editreference import RefTab
from ..glade import Glade
#-------------------------------------------------------------------------
@ -78,49 +82,12 @@ class EditCitation(EditPrimary):
The obj parameter is mandatory. If the source parameter is not
provided, it will be deduced from the obj Citation object.
"""
if not source and obj.get_reference_handle():
source = dbstate.db.get_source_from_handle(
obj.get_reference_handle())
self.source = source
if source:
obj.set_reference_handle(source.get_handle())
self.callertitle = callertitle
EditPrimary.__init__(self, dbstate, uistate, track, obj,
dbstate.db.get_citation_from_handle,
dbstate.db.get_citation_from_gramps_id, callback)
# FIXME: EitPrimary calls ManagedWindow.__init__, which checks whether
# a window is already open which is editing obj. However, for
# EditCitation, not only do we need to protect obj (which will be
# a Citation, but we also need to protect the associated Source.
def build_window_key(self, obj):
"""
Return a key for the edit window that is opened.
This function overrides the build_window_key in EditPrimary.
There is a problem with database object locking. The database locking is
handled by the ManagedWindow class, which will only allow one primary
object to be edited at a time.
Normally, the window key is derived from the obj that is being edited.
However, in the case of EditCitation, there are two objects being
edited, the Citation and the Source. Both must be protected against
against the user trying to edit them twice.
What we do here is to derive the window key from the Source object, if
one exists. A Citation always points to exactly one Source object, so if
we try to edit the same Citation twice, the associated Source objects
will be the same so this will be prevented. If we try to edit a Source
object and a Citation object that refers to the same Source, then again,
the window key will be the same and this will be prevented.
"""
if obj and obj.get_reference_handle():
# citation already points to source
return obj.get_reference_handle()
elif self.source and self.source.get_handle():
# Citation doesn't yet point to source, but source exists and has a
# handle
return self.source.get_handle()
else:
return id(self)
def empty_object(self):
"""
@ -156,68 +123,27 @@ class EditCitation(EditPrimary):
title = _('New Citation')
return title
# 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):
self.warn_box = box
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)
def _local_init(self):
"""Local initialization function.
"""
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.citation-width'
self.height_key = 'interface.citation-height'
assert(self.obj)
self.glade = Glade()
self.set_window(self.glade.toplevel, None,
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')
notebook = self.glade.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.glade.get_object('table68')
notebook = self.glade.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 _post_init(self):
title = self.glade.get_object('title')
volume = self.glade.get_object('volume')
if not title.get_text_length():
title.grab_focus();
elif not volume.get_text_length():
volume.grab_focus();
self.share_btn = self.glade.get_object('select_source')
self.add_del_btn = self.glade.get_object('add_del_source')
def _connect_signals(self):
"""Connects any signals that need to be connected.
"""
Connects any signals that need to be connected.
Called by the init routine of the base class L{EditPrimary}.
"""
@ -234,21 +160,21 @@ class EditCitation(EditPrimary):
whilst editing it. If the object is deleted we need to close the editor
windows and clean up. If the database emits a rebuild signal for the
database object type we also abort the edit.
The Citation editor edits two primary objects, and therefore we need to
check if either have been deleted. If the source is deleted, the
citation must have been deleted first and will emit a signal, so we
shouldn't have to connect to the source-delete signal. It should not be
necessary to connect to the source- rebuild signal for similar reasons.
"""
self._add_db_signal('citation-rebuild', self._do_close)
self._add_db_signal('citation-delete', self.check_for_close)
def _setup_fields(self):
"""Get control widgets and attach them to Citation's attributes."""
# Populate the Citation section
"""
Get control widgets and attach them to Citation's attributes.
"""
self.source_field = SourceEntry(self.dbstate, self.uistate, self.track,
self.glade.get_object("source"),
self.obj.set_reference_handle,
self.obj.get_reference_handle,
self.add_del_btn, self.share_btn,
callback=self.source_changed)
self.date = MonitoredDate(
self.glade.get_object("date_entry"),
@ -259,7 +185,7 @@ class EditCitation(EditPrimary):
self.db.readonly)
self.gid = MonitoredEntry(
self.glade.get_object('gid2'), self.obj.set_gramps_id,
self.glade.get_object('gid'), self.obj.set_gramps_id,
self.obj.get_gramps_id,self.db.readonly)
self.volume = MonitoredEntry(
@ -279,105 +205,49 @@ class EditCitation(EditPrimary):
self.ref_privacy = PrivacyButton(
self.glade.get_object('privacy'), self.obj, self.db.readonly)
# Populate the Source section
self.title = MonitoredEntry(
self.glade.get_object('title'),
self.source.set_title,
self.source.get_title,
self.db.readonly)
self.author = MonitoredEntry(
self.glade.get_object('author'), self.source.set_author,
self.source.get_author,self.db.readonly)
self.gid = MonitoredEntry(
self.glade.get_object('gid'), self.source.set_gramps_id,
self.source.get_gramps_id,self.db.readonly)
self.source_privacy = PrivacyButton(
self.glade.get_object("private"),
self.source, self.db.readonly)
self.abbrev = MonitoredEntry(
self.glade.get_object('abbrev'), self.source.set_abbreviation,
self.source.get_abbreviation,self.db.readonly)
self.pubinfo = MonitoredEntry(
self.glade.get_object('pub_info'), self.source.set_publication_info,
self.source.get_publication_info,self.db.readonly)
def _create_tabbed_pages(self):
"""
Create the notebook tabs and inserts them into the main
window.
"""
# create notebook tabs for Citation
notebook_ref = self.glade.get_object('notebook_ref')
self._add_tab(notebook_ref, self.reftab)
notebook = Gtk.Notebook()
self.comment_tab = NoteTab(self.dbstate, self.uistate, self.track,
self.note_tab = NoteTab(self.dbstate, self.uistate, self.track,
self.obj.get_note_list(), self.get_menu_title(),
notetype=NoteType.CITATION)
self._add_tab(notebook_ref, self.comment_tab)
self.track_ref_for_deletion("comment_tab")
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_ref, self.gallery_tab)
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_ref, self.data_tab)
self._add_tab(notebook, self.data_tab)
self.track_ref_for_deletion("data_tab")
self.citationref_list = CitationBackRefList(self.dbstate, self.uistate,
self.track,
self.db.find_backlink_handles(self.obj.handle),
self.enable_warnbox2)
self._add_tab(notebook_ref, self.citationref_list)
self.db.find_backlink_handles(self.obj.handle))
self._add_tab(notebook, self.citationref_list)
self.track_ref_for_deletion("citationref_list")
# Create notebook tabs for Source
notebook_src = self.glade.get_object('notebook_src')
self._add_tab(notebook_src, self.primtab)
self.note_tab = NoteTab(self.dbstate, self.uistate, self.track,
self.source.get_note_list(),
self.get_menu_title(),
notetype=NoteType.SOURCE)
self._add_tab(notebook_src, self.note_tab)
self.track_ref_for_deletion("note_tab")
self.gallery_tab = GalleryTab(self.dbstate, self.uistate, self.track,
self.source.get_media_list())
self._add_tab(notebook_src, self.gallery_tab)
self.track_ref_for_deletion("gallery_tab")
self.data_tab = DataEmbedList(self.dbstate, self.uistate, self.track,
self.source)
self._add_tab(notebook_src, self.data_tab)
self.track_ref_for_deletion("data_tab")
self.repo_tab = RepoEmbedList(self.dbstate, self.uistate, self.track,
self.source.get_reporef_list())
self._add_tab(notebook_src, self.repo_tab)
self.track_ref_for_deletion("repo_tab")
self.srcref_list = SourceBackRefList(self.dbstate, self.uistate,
self.track,
self.db.find_backlink_handles(self.source.handle),
self.enable_warnbox)
self._add_tab(notebook_src, self.srcref_list)
self.track_ref_for_deletion("srcref_list")
self._setup_notebook_tabs(notebook)
self._setup_notebook_tabs(notebook_src)
self._setup_notebook_tabs(notebook_ref)
notebook.show_all()
self.glade.get_object('vbox').pack_start(notebook, True, True, 0)
def source_changed(self):
handle = self.obj.get_reference_handle()
if handle:
source = self.db.get_source_from_handle(handle)
author = source.get_author()
else:
author = ''
self.glade.get_object("author").set_text(author)
def build_menu_names(self, source):
"""
@ -387,12 +257,13 @@ class EditCitation(EditPrimary):
return (_('Edit Citation'), self.get_menu_title())
def save(self, *obj):
"""Save the data."""
"""
Save the data.
"""
self.ok_button.set_sensitive(False)
if self.source_is_empty(self.source):
ErrorDialog(_("Cannot save source"),
_("No data exists for this source. Please "
"enter data or cancel the edit."))
if not self.obj.get_reference_handle():
ErrorDialog(_("Cannot save citation. No source selected."),
_("Please select a source or cancel the edit."))
self.ok_button.set_sensitive(True)
return
@ -410,78 +281,24 @@ class EditCitation(EditPrimary):
self.ok_button.set_sensitive(True)
return
(uses_dupe_id, gramps_id) = self.source_uses_duplicate_id(self.source)
if uses_dupe_id:
prim_object = self.db.get_source_from_gramps_id(gramps_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 %(gramps_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.") % {
'gramps_id' : gramps_id, 'prim_object' : name }
ErrorDialog(msg1, msg2)
self.ok_button.set_sensitive(True)
return
with DbTxn('', self.db) as trans:
# First commit the Source Primary object
if not self.source.get_handle():
self.db.add_source(self.source, trans)
msg = _("Add Source (%s)") % self.source.get_title()
else:
if not self.source.get_gramps_id():
self.source.set_gramps_id(
self.db.find_next_source_gramps_id())
self.db.commit_source(self.source, trans)
msg = _("Edit Source (%s)") % self.source.get_title()
self.obj.set_reference_handle(self.source.handle)
# Now commit the Citation Primary object
if not self.obj.get_handle():
self.db.add_citation(self.obj, trans)
msg += "\n" + _("Add Citation (%s)") % self.obj.get_page()
msg = _("Add Citation (%s)") % self.obj.get_page()
else:
if not self.obj.get_gramps_id():
self.obj.set_gramps_id(
self.db.find_next_citation_gramps_id())
self.db.commit_citation(self.obj, trans)
msg += "\n" + _("Edit Citation (%s)") % self.obj.get_page()
msg = _("Edit Citation (%s)") % self.obj.get_page()
trans.set_description(msg)
if self.callback:
self.callback(self.obj.get_handle())
self.close()
def source_is_empty(self, obj):
empty_object = Source()
return obj.serialize()[1:] == empty_object.serialize()[1:]
def source_uses_duplicate_id(self, obj):
"""
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.db.get_source_from_handle(obj.get_handle())
if original and original.get_gramps_id() == obj.get_gramps_id():
return (False, 0)
else:
idval = obj.get_gramps_id()
if self.db.get_source_from_gramps_id(idval):
return (True, idval)
return (False, 0)
def data_has_changed(self):
return self.citation_data_has_changed() or \
self.source_data_has_changed()
def citation_data_has_changed(self):
"""
This checks whether the citation data has changed
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
@ -500,23 +317,6 @@ class EditCitation(EditPrimary):
cmp_obj = self.empty_object()
return cmp_obj.serialize(True)[1:] != self.obj.serialize()[1:]
def source_data_has_changed(self):
"""
This checks whether the source data has changed
"""
if self.db.readonly:
return False
elif self.source.handle:
orig = self.db.get_source_from_handle(self.source.handle)
if orig:
cmp_obj = orig
else:
cmp_obj = Source()
return cmp_obj.serialize()[1:] != self.source.serialize()[1:]
else:
cmp_obj = Source()
return cmp_obj.serialize()[1:] != self.source.serialize()[1:]
class DeleteCitationQuery(object):
def __init__(self, dbstate, uistate, citation, the_lists):
self.citation = citation

View File

@ -67,7 +67,7 @@ class EditSource(EditPrimary):
EditPrimary.__init__(self, dbstate, uistate, track, source,
dbstate.db.get_source_from_handle,
dbstate.db.get_source_from_gramps_id)
dbstate.db.get_source_from_gramps_id, callback)
def empty_object(self):
return Source()
@ -211,6 +211,8 @@ class EditSource(EditPrimary):
trans.set_description(msg)
self.close()
if self.callback:
self.callback(self.obj)
class DeleteSrcQuery(object):
def __init__(self, dbstate, uistate, source, the_lists):

View File

@ -50,8 +50,9 @@ from gi.repository import Pango
# Gramps modules
#
#-------------------------------------------------------------------------
from gramps.gen.lib import (Place, MediaObject, Note)
from gramps.gen.lib import (Place, Source, MediaObject, Note)
from .editplace import EditPlace
from .editsource import EditSource
from .editmedia import EditMedia
from .editnote import EditNote
from ..selectors import SelectorFactory
@ -77,7 +78,7 @@ class ObjEntry(object):
DEL_STR = ""
def __init__(self, dbstate, uistate, track, label, set_val,
get_val, add_edt, share):
get_val, add_edt, share, callback=None):
"""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
@ -97,6 +98,7 @@ class ObjEntry(object):
self.set_val = set_val
self.uistate = uistate
self.track = track
self.callback = callback
#connect drag and drop
self._init_dnd()
@ -140,6 +142,8 @@ class ObjEntry(object):
else:
self.label.set_text(name)
self.label.set_ellipsize(Pango.EllipsizeMode.END)
if self.callback:
self.callback()
def _init_dnd(self):
"""inheriting objects must set this
@ -166,6 +170,8 @@ class ObjEntry(object):
def after_edit(self, obj):
name = self.get_label(obj)
self.label.set_text(name)
if self.callback:
self.callback()
def add_edt_clicked(self, obj):
""" if value, edit, if no value, call editor on new object
@ -197,6 +203,8 @@ class ObjEntry(object):
self.set_val(data.handle)
self.label.set_text(self.get_label(data))
self.set_button(True)
if self.callback:
self.callback()
def share_clicked(self, obj):
""" if value, delete connect, in no value, select existing object
@ -206,6 +214,8 @@ class ObjEntry(object):
self.label.set_text(self.EMPTY_TEXT)
self.label.set_use_markup(True)
self.set_button(False)
if self.callback:
self.callback()
else:
select = self.call_selector()
obj = select.run()
@ -300,6 +310,60 @@ class PlaceEntry(ObjEntry):
cls = SelectorFactory('Place')
return cls(self.dbstate, self.uistate, self.track)
class SourceEntry(ObjEntry):
"""
Handles the selection of a existing or new Source. Supports Drag and Drop
to select a source.
"""
EMPTY_TEXT = "<i>%s</i>" % _('To select a source, 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 source')
SHARE_STR = _('Select an existing source')
ADD_STR = _('Add a new source')
DEL_STR = _('Remove source')
def __init__(self, dbstate, uistate, track, label, set_val,
get_val, add_edt, share, callback):
ObjEntry.__init__(self, dbstate, uistate, track, label, set_val,
get_val, add_edt, share, callback)
def _init_dnd(self):
"""connect drag and drop of sources
"""
self.label.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
tglist = Gtk.TargetList.new([])
tglist.add(DdTargets.PLACE_LINK.atom_drag_type,
DdTargets.PLACE_LINK.target_flags,
DdTargets.PLACE_LINK.app_id)
self.label.drag_dest_set_target_list(tglist)
self.label.connect('drag_data_received', self.drag_data_received)
def get_from_handle(self, handle):
""" return the object given the handle
"""
return self.db.get_source_from_handle(handle)
def get_label(self, source):
return "%s [%s]" % (source.get_title(), source.gramps_id)
def call_editor(self, obj=None):
if obj is None:
source = Source()
func = self.obj_added
else:
source = obj
func = self.after_edit
try:
EditSource(self.dbstate, self.uistate, self.track,
source, func)
except WindowActiveError:
pass
def call_selector(self):
cls = SelectorFactory('Source')
return cls(self.dbstate, self.uistate, self.track)
# FIXME isn't used anywhere
class MediaEntry(ObjEntry):
"""

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<!-- interface-requires grampswidgets 0.0 -->
<object class="GtkListStore" id="confidence_model">
<columns>
<!-- column-name gchararray1 -->
@ -12,7 +13,7 @@
<property name="default_width">600</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox17">
<object class="GtkBox" id="vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child internal-child="action_area">
@ -23,12 +24,10 @@
<child>
<object class="GtkButton" id="help">
<property name="label">gtk-help</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -40,12 +39,10 @@
<child>
<object class="GtkButton" id="cancel">
<property name="label">gtk-cancel</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -57,12 +54,10 @@
<child>
<object class="GtkButton" id="ok">
<property name="label">gtk-ok</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -80,146 +75,139 @@
</packing>
</child>
<child>
<object class="GtkLabel" id="label602">
<object class="GtkTable" id="table67">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">6</property>
<property name="ypad">3</property>
<property name="label" translatable="yes">&lt;b&gt;Citation information&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkNotebook" id="notebook_ref">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="border_width">6</property>
<property name="border_width">12</property>
<property name="n_rows">5</property>
<property name="n_columns">4</property>
<property name="column_spacing">12</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkTable" id="table67">
<object class="GtkLabel" id="label612">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="n_rows">5</property>
<property name="n_columns">3</property>
<property name="column_spacing">12</property>
<property name="row_spacing">6</property>
<child>
<placeholder/>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Date:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">date_entry</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkButton" id="date_stat">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="has_tooltip">True</property>
<property name="tooltip_text" translatable="yes">Invoke date editor</property>
<property name="relief">none</property>
<accelerator key="d" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<child internal-child="accessible">
<object class="AtkObject" id="date_stat-atkobject">
<property name="AtkObject::accessible-name" translatable="yes">Date</property>
</object>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkLabel" id="label612">
<object class="GtkImage" id="image2682">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">_Date:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">date_entry</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkButton" id="date_stat">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="has_tooltip">True</property>
<property name="tooltip_text" translatable="yes">Invoke date editor</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<accelerator key="d" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<property name="icon_name">gramps-date</property>
<child internal-child="accessible">
<object class="AtkObject" id="date_stat-atkobject">
<property name="AtkObject::accessible-name" translatable="yes">Date</property>
</object>
</child>
<child>
<object class="GtkImage" id="image2682">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">gramps-date</property>
<child internal-child="accessible">
<object class="AtkObject" id="image2682-atkobject">
<property name="AtkObject::accessible-description" translatable="yes">Date</property>
</object>
</child>
<object class="AtkObject" id="image2682-atkobject">
<property name="AtkObject::accessible-description" translatable="yes">Date</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="UndoableEntry" id="volume">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Specific location within the information referenced. For a published work, this could include the volume of a multi-volume work and the page number(s). For a periodical, it could include volume, issue, and page numbers. For a newspaper, it could include a column number and page number. For an unpublished source, this could be a sheet number, page number, frame number, etc. A census record might have a line number or dwelling and family numbers in addition to the page number. </property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label613">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">_Volume/Page:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">volume</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label614">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Con_fidence:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">confidence</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="UndoableEntry" id="volume">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Specific location within the information referenced. For a published work, this could include the volume of a multi-volume work and the page number(s). For a periodical, it could include volume, issue, and page numbers. For a newspaper, it could include a column number and page number. For an unpublished source, this could be a sheet number, page number, frame number, etc. A census record might have a line number or dwelling and family numbers in addition to the page number. </property>
<property name="invisible_char">•</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label613">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Volume/Page:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">volume</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label614">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Con_fidence:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="ValidatableMaskedEntry" id="date_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">The date of the entry in the source you are referencing, e.g. the date a house was visited during a census, or the date an entry was made in a birth log/registry. </property>
<property name="invisible_char">•</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkComboBox" id="confidence">
<property name="visible">True</property>
@ -238,131 +226,9 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="ValidatableMaskedEntry" id="date_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">The date of the entry in the source you are referencing, e.g. the date a house was visited during a census, or the date an entry was made in a birth log/registry. </property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkHBox" id="warn_box2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkImage" id="warn_icon2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-dialog-warning</property>
<property name="icon-size">6</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="warn_text2">
<property name="width_request">500</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="ypad">3</property>
<property name="label" translatable="yes">&lt;b&gt;Note:&lt;/b&gt; Any changes in the shared citation information will be reflected in the citation itself, for all items that reference the citation.</property>
<property name="use_markup">True</property>
<property name="use_underline">True</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="UndoableEntry" id="gid2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">A unique ID to identify the citation</property>
<property name="invisible_char">•</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="privacy">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<child internal-child="accessible">
<object class="AtkObject" id="privacy-atkobject">
<property name="AtkObject::accessible-name" translatable="yes">Private</property>
</object>
</child>
<child>
<object class="GtkImage" id="image2677">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">gtk-dialog-authentication</property>
<child internal-child="accessible">
<object class="AtkObject" id="image2677-atkobject">
<property name="AtkObject::accessible-description" translatable="yes">Privacy</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
@ -372,357 +238,176 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="xalign">1</property>
<property name="label" translatable="yes">_ID:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">gid2</property>
<property name="mnemonic_widget">gid</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="UndoableEntry" id="gid">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">A unique ID to identify the citation</property>
<property name="invisible_char">•</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child type="tab">
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Source:</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkButton" id="add_del_source">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="relief">none</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="source">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="select_source">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="relief">none</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="privacy">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="relief">none</property>
<accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<child internal-child="accessible">
<object class="AtkObject" id="privacy-atkobject">
<property name="AtkObject::accessible-name" translatable="yes">Private</property>
</object>
</child>
<child>
<object class="GtkImage" id="image2677">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">gtk-dialog-authentication</property>
<child internal-child="accessible">
<object class="AtkObject" id="image2677-atkobject">
<property name="AtkObject::accessible-description" translatable="yes">Privacy</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;General&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Author:</property>
</object>
<packing>
<property name="tab_fill">False</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="author">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkExpander" id="src_expander">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="border_width">6</property>
<property name="expanded">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkNotebook" id="notebook_src">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="show_border">False</property>
<child>
<object class="GtkTable" id="table68">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="n_rows">6</property>
<property name="n_columns">2</property>
<property name="column_spacing">12</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkLabel" id="label603">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Title:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">title</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label604">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Author:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">author</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label606">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="ypad">3</property>
<property name="label" translatable="yes">A_bbreviation:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">abbrev</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label607">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Pub. Info.:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">pub_info</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="UndoableEntry" id="author">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Authors of the source.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkHBox" id="warn_box">
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="spacing">12</property>
<child>
<object class="GtkImage" id="warn_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-dialog-warning</property>
<property name="icon-size">6</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="warn_text">
<property name="width_request">500</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="ypad">3</property>
<property name="label" translatable="yes">&lt;b&gt;Note:&lt;/b&gt; Any changes in the shared source information will be reflected in the source itself, for all items that reference the source.</property>
<property name="use_markup">True</property>
<property name="use_underline">True</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="UndoableEntry" id="abbrev">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Provide a short title used for sorting, filing, and retrieving source records.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="UndoableEntry" id="pub_info">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Publication Information, such as city and year of publication, name of publisher, ...</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label611">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_ID:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">gid</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox135">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="UndoableEntry" id="gid">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">A unique ID to identify the source</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="private">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child internal-child="accessible">
<object class="AtkObject" id="private-atkobject">
<property name="AtkObject::accessible-name" translatable="yes">Private</property>
</object>
</child>
<child>
<object class="GtkImage" id="image2709">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">gtk-dialog-authentication</property>
<child internal-child="accessible">
<object class="AtkObject" id="image2709-atkobject">
<property name="AtkObject::accessible-description" translatable="yes">Privacy</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="UndoableEntry" id="title">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Title of the source.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options"/>
</packing>
</child>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child type="tab">
<object class="GtkHBox" id="hbox127">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="image2681">
<property name="can_focus">False</property>
<property name="stock">gtk-file</property>
<property name="icon-size">1</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label609">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;General&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label610">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Shared source information&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
<property name="position">1</property>
</packing>
</child>
</object>