GEP 18: allow viewing of different citations in source editor

Start of merging editsource and editcitation


svn: r22481
This commit is contained in:
Benny Malengier
2013-06-05 07:34:47 +00:00
parent 8e922b562d
commit b28bd17980
6 changed files with 513 additions and 20 deletions

View File

@@ -609,7 +609,7 @@ class EmbeddedList(ButtonTab):
@type prebuildpath: tree path
"""
pass
def rebuild_callback(self):
"""
The view must be remade when data changes outside this tab.

View File

@@ -365,6 +365,16 @@ class GalleryTab(ButtonTab, DbGUIElement):
"""
self.rebuild()
def rebuild_callback(self):
"""
The view must be remade when data changes outside this tab.
Use this method to connect to after a db change. It makes sure the
data is obtained again from the present object and the db what is not
present in the obj, and the view rebuild
"""
self.changed = True
self.rebuild()
def media_delete(self, del_media_handle_list):
"""
Outside of this tab media objects have been deleted. Check if tab

View File

@@ -45,7 +45,7 @@ from gi.repository import Gtk, Gdk
# gramps modules
#
#-------------------------------------------------------------------------
from gramps.gen.lib import NoteType, Source, SrcTemplate
from gramps.gen.lib import NoteType, Source, SrcTemplate, Citation
from gramps.gen.db import DbTxn
from gramps.gen.utils.file import media_path_full
from ..thumbnails import get_thumbnail_image
@@ -56,7 +56,8 @@ from .editmediaref import EditMediaRef
from .displaytabs import (NoteTab, GalleryTab, SrcAttrEmbedList,
SrcTemplateTab, CitedInTab,
CitationBackRefList, RepoEmbedList)
from ..widgets import MonitoredEntry, PrivacyButton, MonitoredTagList
from ..widgets import (MonitoredEntry, PrivacyButton, MonitoredTagList,
MonitoredMenu)
from ..dialog import ErrorDialog
from ..utils import is_right_click, open_file_with_default_application
from ..glade import Glade
@@ -69,12 +70,34 @@ from ..glade import Glade
class EditSource(EditPrimary):
def __init__(self, dbstate, uistate, track, source):
def __init__(self, dbstate, uistate, track, source, citation=None,
callback=None,
callertitle = None):
"""
Editor for source and citations of that source
If source is not given, citation must be given, and the source of the
citation will be used
"""
self.srctemp = None
self.citation = None
self.citation = citation
if not source and not citation:
raise NotImplementedError
elif not source:
#citation will be used to obtain the source
hsource = citation.get_reference_handle()
source = dbstate.db.get_source_from_handle(hsource)
elif citation:
#source and citation are given, they MUST be connected or citation
#must be a new object
if citation.get_reference_handle() and \
not (citation.get_reference_handle() == source.handle):
raise Exception('Citation must be a Citation of the Source edited')
self.callertitle = callertitle
self.citation_ready = False
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()
@@ -85,6 +108,23 @@ class EditSource(EditPrimary):
title = _('Source') + ": " + title
else:
title = _('New Source')
if self.citation is not None:
citeid = self.citation.get_gramps_id()
if citeid:
if self.callertitle:
title = _('Citation: %(id)s - %(context)s' % {
'id' : citeid,
'context' : self.callertitle
}) + ' ' + title
else:
title = _('Citation') + ": " + citeid + ' ' + title
else:
if self.callertitle:
title = _('New Citation - %(context)s' % {
'context' : self.callertitle
}) + ' ' + title
else:
title = _('New Citation') + ' ' + title
return title
def _local_init(self):
@@ -99,6 +139,10 @@ class EditSource(EditPrimary):
self.obj_photo = self.glade.get_object("sourcePix")
self.frame_photo = self.glade.get_object("frame5")
self.eventbox = self.glade.get_object("eventbox1")
self.notebook_ref = self.glade.get_object('notebook_citation')
self.cinf = self.glade.get_object("cite_info_lbl")
self.define_warn_box2(self.glade.get_object("warn_box2"))
def _post_init(self):
"""
@@ -110,6 +154,9 @@ class EditSource(EditPrimary):
derived class (this class).
"""
if self.citation is None:
self.unload_citation()
self.load_source_image()
self.title.grab_focus()
@@ -161,6 +208,8 @@ class EditSource(EditPrimary):
Connect any signals that need to be connected.
Called by the init routine of the base class (_EditPrimary).
"""
self._add_db_signal('citation-rebuild', self._do_close)
self._add_db_signal('citation-delete', self.check_for_close_cite)
self._add_db_signal('source-rebuild', self._do_close)
self._add_db_signal('source-delete', self.check_for_close)
self._add_db_signal('note-delete', self.update_notes)
@@ -168,6 +217,17 @@ class EditSource(EditPrimary):
self._add_db_signal('note-add', self.update_notes)
self._add_db_signal('note-rebuild', self.update_notes)
def check_for_close_cite(self, handles):
"""
Callback method for delete signals.
If there is a delete signal of the citation object we are
editing, the
editor (and all child windows spawned) should be closed
"""
#citation, we only close if that citation is open
if self.citation and self.citation.get_handle() in handles:
self._do_close()
def _setup_fields(self):
## self.author = MonitoredEntry(self.glade.get_object("author"),
## self.obj.set_author, self.obj.get_author,
@@ -177,7 +237,7 @@ class EditSource(EditPrimary):
## self.obj.set_publication_info,
## self.obj.get_publication_info,
## self.db.readonly)
#reference info fields
#reference info fields of source
self.refL = self.glade.get_object("refL")
self.refF = self.glade.get_object("refF")
self.refS = self.glade.get_object("refS")
@@ -185,6 +245,7 @@ class EditSource(EditPrimary):
self.pubinfo = self.glade.get_object("pubinfo")
self.source_text = self.glade.get_object("source_text")
#editable source fields
self.gid = MonitoredEntry(self.glade.get_object("gid"),
self.obj.set_gramps_id,
self.obj.get_gramps_id, self.db.readonly)
@@ -209,9 +270,44 @@ class EditSource(EditPrimary):
self.obj.set_title, self.obj.get_title,
self.db.readonly)
#editable citation fields
if self.citation:
self._setup_citation_fields()
#trigger updates of read only fields
self.update_attr()
self.update_notes()
def _setup_citation_fields(self):
if self.citation_ready:
raise Exception
self.gid = MonitoredEntry(
self.glade.get_object('gid2'), self.citation.set_gramps_id,
self.citation.get_gramps_id, self.db.readonly)
self.type_mon = MonitoredMenu(
self.glade.get_object('confidence'),
self.citation.set_confidence_level,
self.citation.get_confidence_level, [
(_('Very Low'), Citation.CONF_VERY_LOW),
(_('Low'), Citation.CONF_LOW),
(_('Normal'), Citation.CONF_NORMAL),
(_('High'), Citation.CONF_HIGH),
(_('Very High'), Citation.CONF_VERY_HIGH)],
self.db.readonly)
self.tags2 = MonitoredTagList(
self.glade.get_object("tag_label2"),
self.glade.get_object("tag_button2"),
self.citation.set_tag_list,
self.citation.get_tag_list,
self.db,
self.uistate, self.track,
self.db.readonly)
self.ref_privacy = PrivacyButton(
self.glade.get_object('privacy'), self.citation, self.db.readonly)
def update_attr(self):
"""
Reaction to update on attributes
@@ -325,7 +421,54 @@ class EditSource(EditPrimary):
self._setup_notebook_tabs(notebook)
notebook.show_all()
self.glade.get_object('vbox').pack_start(notebook, True, True, 0)
#now create citation tabbed pages
if self.citation:
self._create_citation_tabbed_pages()
def _create_citation_tabbed_pages(self):
if self.citation_ready:
raise Exception
self.citation_ready = True
tblref = self.glade.get_object('grid1')
notebook_ref = self.notebook_ref
#recreate start page as GrampsTab
notebook_ref.remove_page(0)
self.reftab = RefTab(self.dbstate, self.uistate, self.track,
_('General'), tblref)
self._add_tab(notebook_ref, self.reftab)
self.track_ref_for_deletion("reftab")
self.comment_tab = NoteTab(self.dbstate, self.uistate, self.track,
self.citation.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.gallery_tab = GalleryTab(self.dbstate, self.uistate, self.track,
self.citation.get_media_list())
self._add_tab(notebook_ref, self.gallery_tab)
self.track_ref_for_deletion("gallery_tab")
self.attr_tab = SrcAttrEmbedList(self.dbstate, self.uistate, self.track,
self.citation.get_attribute_list())
self._add_tab(notebook_ref, self.attr_tab)
self.track_ref_for_deletion("attr_tab")
self.citationref_list = CitationBackRefList(self.dbstate, self.uistate,
self.track,
self.db.find_backlink_handles(self.citation.handle),
self.enable_warnbox2)
self._add_tab(notebook_ref, self.citationref_list)
self.track_ref_for_deletion("citationref_list")
def define_warn_box2(self, box):
self.warn_box2 = box
def enable_warnbox2(self):
self.warn_box2.show()
def build_menu_names(self, source):
return (_('Edit Source'), self.get_menu_title())
@@ -442,15 +585,48 @@ class EditSource(EditPrimary):
self.load_citation(citation_handle)
def unload_citation(self):
pass
self.cinf.set_visible(False)
self.notebook_ref.set_visible(False)
if self.citation:
#there is a citation, we clear it
self.citation.unserialize(Citation().serialize())
def load_citation(self, chandle):
if self.citation:
raise Exception("Request to change citation, but another citation loaded")
self.citation = chandle
#we switch current citatoin for the new one
if not self.citation:
#there is no citation yet, put an empty one
self.citation = Citation()
if chandle:
newcite = self.db.get_citation_from_handle(chandle)
else:
newcite = Citation()
if not newcite:
#error in database, link to citation handle that does not exist
raise Exception
self.citation.unserialize(newcite.serialize())
if not self.citation_ready:
self._setup_citation_fields()
self._create_citation_tabbed_pages()
else:
self.citation_changed()
self.cinf.set_visible(True)
self.notebook_ref.set_visible(True)
def citation_changed(self):
"""
The citation part of the editor changed, we need to update all
GUI fields showing data of it
"""
#update source part that uses citation
self.update_attr()
#trigger update of the monitored fields
for field in [self.gid, self.type_mon, self.tags2, self.ref_privacy]:
field.update()
#trigger update of the tab fields
for tab in [self.comment_tab, self.gallery_tab, self.attr_tab,
self.citationref_list]:
tab.rebuild_callback()
class DeleteSrcQuery(object):
def __init__(self, dbstate, uistate, source, the_lists):
self.source = source

View File

@@ -79,10 +79,305 @@
<object class="GtkVBox" id="vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="cite_info_lbl">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">&lt;b&gt;Citation Information&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkNotebook" id="notebook_citation">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">3</property>
<property name="column_spacing">3</property>
<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>
<property name="mnemonic_widget">confidence</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="confidence">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="entry_text_column">0</property>
<property name="id_column">1</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</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="halign">center</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">2</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label17">
<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">gid2</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">3</property>
<child>
<object class="GtkEntry" id="gid2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">•</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label18">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Tags:</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="tag_label2">
<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">2</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="tag_button2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</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="left_attach">0</property>
<property name="top_attach">4</property>
<property name="width">3</property>
<property name="height">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="tab">
<object class="GtkLabel" id="label14">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Overview</property>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child type="tab">
<object class="GtkLabel" id="label15">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 2</property>
</object>
<packing>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child type="tab">
<object class="GtkLabel" id="label16">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 3</property>
</object>
<packing>
<property name="position">2</property>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="source_info_lbl">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">&lt;b&gt;Source Information&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkNotebook" id="notebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkGrid" id="gridsrc">
<property name="visible">True</property>
@@ -763,7 +1058,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">3</property>
</packing>
</child>
</object>

View File

@@ -182,3 +182,7 @@ class PrivacyButton(object):
self.obj.set_privacy(False)
image.show()
obj.add(image)
def update(self):
""" force an update so as to correspond with the object monitored"""
self.set_active(self.obj.get_privacy())

View File

@@ -177,6 +177,7 @@ class MonitoredEntry(object):
self.obj.grab_focus()
def update(self):
""" force an update so as to correspond with the object monitored"""
if self.get_val(None) is not None:
self.obj.set_text(self.get_val(None))
@@ -560,6 +561,9 @@ class MonitoredMenu(object):
if self.changed:
self.changed()
def update(self):
""" force an update so as to correspond with the object monitored"""
self.obj.set_active(self.data.get(self.get_val(), 0))
#-------------------------------------------------------------------------
#
# MonitoredStrMenu class
@@ -833,12 +837,7 @@ class MonitoredTagList(object):
self.track = track
self.db = db
self.set_list = set_list
self.tag_list = []
for handle in get_list():
tag = self.db.get_tag_from_handle(handle)
if tag:
self.tag_list.append((handle, tag.get_name()))
self.get_list = get_list
self.all_tags = []
for tag in self.db.iter_tags():
@@ -855,7 +854,7 @@ class MonitoredTagList(object):
button.connect('key-press-event', self.cb_edit)
button.set_sensitive(not readonly)
self._display()
self.update()
## def destroy(self):
## """
@@ -890,3 +889,12 @@ class MonitoredTagList(object):
self.set_list([item[0] for item in self.tag_list])
return True
return False
def update(self):
""" force an update so as to correspond with the object monitored"""
self.tag_list = []
for handle in self.get_list():
tag = self.db.get_tag_from_handle(handle)
if tag:
self.tag_list.append((handle, tag.get_name()))
self._display()