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 @type prebuildpath: tree path
""" """
pass pass
def rebuild_callback(self): def rebuild_callback(self):
""" """
The view must be remade when data changes outside this tab. The view must be remade when data changes outside this tab.

View File

@@ -365,6 +365,16 @@ class GalleryTab(ButtonTab, DbGUIElement):
""" """
self.rebuild() 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): def media_delete(self, del_media_handle_list):
""" """
Outside of this tab media objects have been deleted. Check if tab 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 # 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.db import DbTxn
from gramps.gen.utils.file import media_path_full from gramps.gen.utils.file import media_path_full
from ..thumbnails import get_thumbnail_image from ..thumbnails import get_thumbnail_image
@@ -56,7 +56,8 @@ from .editmediaref import EditMediaRef
from .displaytabs import (NoteTab, GalleryTab, SrcAttrEmbedList, from .displaytabs import (NoteTab, GalleryTab, SrcAttrEmbedList,
SrcTemplateTab, CitedInTab, SrcTemplateTab, CitedInTab,
CitationBackRefList, RepoEmbedList) CitationBackRefList, RepoEmbedList)
from ..widgets import MonitoredEntry, PrivacyButton, MonitoredTagList from ..widgets import (MonitoredEntry, PrivacyButton, MonitoredTagList,
MonitoredMenu)
from ..dialog import ErrorDialog from ..dialog import ErrorDialog
from ..utils import is_right_click, open_file_with_default_application from ..utils import is_right_click, open_file_with_default_application
from ..glade import Glade from ..glade import Glade
@@ -69,12 +70,34 @@ from ..glade import Glade
class EditSource(EditPrimary): 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.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, EditPrimary.__init__(self, dbstate, uistate, track, source,
dbstate.db.get_source_from_handle, 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): def empty_object(self):
return Source() return Source()
@@ -85,6 +108,23 @@ class EditSource(EditPrimary):
title = _('Source') + ": " + title title = _('Source') + ": " + title
else: else:
title = _('New Source') 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 return title
def _local_init(self): def _local_init(self):
@@ -99,6 +139,10 @@ class EditSource(EditPrimary):
self.obj_photo = self.glade.get_object("sourcePix") self.obj_photo = self.glade.get_object("sourcePix")
self.frame_photo = self.glade.get_object("frame5") self.frame_photo = self.glade.get_object("frame5")
self.eventbox = self.glade.get_object("eventbox1") 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): def _post_init(self):
""" """
@@ -110,6 +154,9 @@ class EditSource(EditPrimary):
derived class (this class). derived class (this class).
""" """
if self.citation is None:
self.unload_citation()
self.load_source_image() self.load_source_image()
self.title.grab_focus() self.title.grab_focus()
@@ -161,6 +208,8 @@ class EditSource(EditPrimary):
Connect any signals that need to be connected. Connect any signals that need to be connected.
Called by the init routine of the base class (_EditPrimary). 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-rebuild', self._do_close)
self._add_db_signal('source-delete', self.check_for_close) self._add_db_signal('source-delete', self.check_for_close)
self._add_db_signal('note-delete', self.update_notes) 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-add', self.update_notes)
self._add_db_signal('note-rebuild', 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): def _setup_fields(self):
## self.author = MonitoredEntry(self.glade.get_object("author"), ## self.author = MonitoredEntry(self.glade.get_object("author"),
## self.obj.set_author, self.obj.get_author, ## self.obj.set_author, self.obj.get_author,
@@ -177,7 +237,7 @@ class EditSource(EditPrimary):
## self.obj.set_publication_info, ## self.obj.set_publication_info,
## self.obj.get_publication_info, ## self.obj.get_publication_info,
## self.db.readonly) ## self.db.readonly)
#reference info fields #reference info fields of source
self.refL = self.glade.get_object("refL") self.refL = self.glade.get_object("refL")
self.refF = self.glade.get_object("refF") self.refF = self.glade.get_object("refF")
self.refS = self.glade.get_object("refS") self.refS = self.glade.get_object("refS")
@@ -185,6 +245,7 @@ class EditSource(EditPrimary):
self.pubinfo = self.glade.get_object("pubinfo") self.pubinfo = self.glade.get_object("pubinfo")
self.source_text = self.glade.get_object("source_text") self.source_text = self.glade.get_object("source_text")
#editable source fields
self.gid = MonitoredEntry(self.glade.get_object("gid"), self.gid = MonitoredEntry(self.glade.get_object("gid"),
self.obj.set_gramps_id, self.obj.set_gramps_id,
self.obj.get_gramps_id, self.db.readonly) self.obj.get_gramps_id, self.db.readonly)
@@ -209,9 +270,44 @@ class EditSource(EditPrimary):
self.obj.set_title, self.obj.get_title, self.obj.set_title, self.obj.get_title,
self.db.readonly) self.db.readonly)
#editable citation fields
if self.citation:
self._setup_citation_fields()
#trigger updates of read only fields
self.update_attr() self.update_attr()
self.update_notes() 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): def update_attr(self):
""" """
Reaction to update on attributes Reaction to update on attributes
@@ -325,7 +421,54 @@ class EditSource(EditPrimary):
self._setup_notebook_tabs(notebook) self._setup_notebook_tabs(notebook)
notebook.show_all() notebook.show_all()
self.glade.get_object('vbox').pack_start(notebook, True, True, 0) 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): def build_menu_names(self, source):
return (_('Edit Source'), self.get_menu_title()) return (_('Edit Source'), self.get_menu_title())
@@ -442,15 +585,48 @@ class EditSource(EditPrimary):
self.load_citation(citation_handle) self.load_citation(citation_handle)
def unload_citation(self): 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): def load_citation(self, chandle):
if self.citation: #we switch current citatoin for the new one
raise Exception("Request to change citation, but another citation loaded") if not self.citation:
self.citation = chandle #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 #update source part that uses citation
self.update_attr() 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): class DeleteSrcQuery(object):
def __init__(self, dbstate, uistate, source, the_lists): def __init__(self, dbstate, uistate, source, the_lists):
self.source = source self.source = source

View File

@@ -79,10 +79,305 @@
<object class="GtkVBox" id="vbox"> <object class="GtkVBox" id="vbox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</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> <child>
<object class="GtkNotebook" id="notebook"> <object class="GtkNotebook" id="notebook">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="vexpand">True</property>
<child> <child>
<object class="GtkGrid" id="gridsrc"> <object class="GtkGrid" id="gridsrc">
<property name="visible">True</property> <property name="visible">True</property>
@@ -763,7 +1058,7 @@
<packing> <packing>
<property name="expand">True</property> <property name="expand">True</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">3</property>
</packing> </packing>
</child> </child>
</object> </object>

View File

@@ -182,3 +182,7 @@ class PrivacyButton(object):
self.obj.set_privacy(False) self.obj.set_privacy(False)
image.show() image.show()
obj.add(image) 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() self.obj.grab_focus()
def update(self): def update(self):
""" force an update so as to correspond with the object monitored"""
if self.get_val(None) is not None: if self.get_val(None) is not None:
self.obj.set_text(self.get_val(None)) self.obj.set_text(self.get_val(None))
@@ -560,6 +561,9 @@ class MonitoredMenu(object):
if self.changed: if self.changed:
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 # MonitoredStrMenu class
@@ -833,12 +837,7 @@ class MonitoredTagList(object):
self.track = track self.track = track
self.db = db self.db = db
self.set_list = set_list self.set_list = set_list
self.get_list = get_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.all_tags = [] self.all_tags = []
for tag in self.db.iter_tags(): for tag in self.db.iter_tags():
@@ -855,7 +854,7 @@ class MonitoredTagList(object):
button.connect('key-press-event', self.cb_edit) button.connect('key-press-event', self.cb_edit)
button.set_sensitive(not readonly) button.set_sensitive(not readonly)
self._display() self.update()
## def destroy(self): ## def destroy(self):
## """ ## """
@@ -890,3 +889,12 @@ class MonitoredTagList(object):
self.set_list([item[0] for item in self.tag_list]) self.set_list([item[0] for item in self.tag_list])
return True return True
return False 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()