GEP 18: extend functionality of citedin tab

svn: r22473
This commit is contained in:
Benny Malengier 2013-06-03 16:11:13 +00:00
parent 72748498b2
commit 8e922b562d
2 changed files with 180 additions and 62 deletions

View File

@ -29,11 +29,14 @@ from __future__ import print_function
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
import sys
#-------------------------------------------------------------------------
#
# GTK libraries
#
#-------------------------------------------------------------------------
from gi.repository import GObject
from gi.repository import Gdk
from gi.repository import Gtk
@ -42,12 +45,17 @@ from gi.repository import Gtk
# Gramps libraries
#
#-------------------------------------------------------------------------
from gramps.gen.errors import WindowActiveError
from gramps.gen.display.name import displayer as _nd
from gramps.gen.utils.db import (get_citation_referents, family_name,
get_participant_from_event)
from .grampstab import GrampsTab
from ...widgets import SimpleButton
_KP_ENTER = Gdk.keyval_from_name("KP_Enter")
_RETURN = Gdk.keyval_from_name("Return")
#-------------------------------------------------------------------------
#
# Classes
@ -60,7 +68,7 @@ class CitedInTab(GrampsTab):
It shows these objects in a treeviewl and allows to load citations in the
top part of the source editor.
"""
def __init__(self, dbstate, uistate, track, src):
def __init__(self, dbstate, uistate, track, src, cite_apply_callback):
"""
@param dbstate: The database state. Contains a reference to
the database, along with other state information. The GrampsTab
@ -80,6 +88,7 @@ class CitedInTab(GrampsTab):
self.src = src
self.readonly = dbstate.db.readonly
self.srtdata = []
self.cite_apply_callback = cite_apply_callback
GrampsTab.__init__(self, dbstate, uistate, track, _("Cited In"))
self._set_label()
@ -102,6 +111,53 @@ class CitedInTab(GrampsTab):
"""
return len(self.srtdata) == 0
def setup_interface(self):
"""
Set all information on the widgets
* button tabs to load citation
* treeview in scrollable with info
"""
##print (self.srtdata)
##print(self.obj2citemap)
#create the load button, add it to a hbox, and add that box to the
#tab page
self.load_btn = SimpleButton(Gtk.STOCK_APPLY, self.apply_button_clicked)
self.load_btn.set_tooltip_text(_("Apply a selected citation so as to"
" edit it in the top part of this interface"))
self.edit_btn = SimpleButton(Gtk.STOCK_EDIT, self.edit_button_clicked)
self.edit_btn.set_tooltip_text(_("Edit the object containing the"
" selected citation"))
hbox = Gtk.HBox()
hbox.set_spacing(6)
hbox.pack_start(self.load_btn, False, True, 0)
hbox.pack_start(self.edit_btn, False, True, 0)
hbox.show_all()
self.pack_start(hbox, False, True, 0)
if self.dbstate.db.readonly:
self.load_btn.set_sensitive(False)
# create the tree, turn on rule hinting and connect the
# button press to the double click function.
self.tree = Gtk.TreeView()
self.tree.set_rules_hint(True)
self.tree.connect('button_press_event', self.double_click)
self.tree.connect('key_press_event', self.key_pressed)
self.make_columns()
self.tree.set_model(self.model)
self.selection = self.tree.get_selection()
# create the scrolled window, and attach the treeview
scroll = Gtk.ScrolledWindow()
scroll.set_shadow_type(Gtk.ShadowType.IN)
scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scroll.add(self.tree)
#add this to the tab
self.pack_start(scroll, True, True, 0)
def generate_data(self):
"""
Obtain all objects this source is cited in
@ -150,7 +206,7 @@ class CitedInTab(GrampsTab):
"outside citation")
self.srtdata = sorted(self.srtdata, key=lambda x: glocale.sort_key(x[0]))
def __add_object(self, obj, cite, descr_obj, shortdescr):
def __add_object(self, obj, cite, descr_obj, shortdescr, objname):
"""
obtain citation data of the object and store here so it can be shown
in a treeview
@ -158,7 +214,7 @@ class CitedInTab(GrampsTab):
if not obj.handle in self.obj2citemap:
self.obj2citemap[obj.handle] = {'prim': [], 'sec': [], 'subsec': []}
#add for sorting in the treeview to map
self.srtdata.append((descr_obj, obj.handle, shortdescr))
self.srtdata.append((descr_obj, obj.handle, shortdescr, objname))
#we analyse the object to determine where the citation is used.
if hasattr(obj, 'get_citation_list'):
for citehandle in obj.get_citation_list():
@ -195,7 +251,7 @@ class CitedInTab(GrampsTab):
name = _nd.display_name(obj.get_primary_name())
self.__add_object(obj, cite, _("Person %(id)s: %(descr)s") % {
'id': obj.get_gramps_id(),
'descr': name}, _("Cited in Person"))
'descr': name}, _("Cited in Person"), "Person")
def __add_family(self, obj, cite):
"""
@ -204,7 +260,7 @@ class CitedInTab(GrampsTab):
name = family_name(obj, self.dbstate.db, _("Unknown Family"))
self.__add_object(obj, cite, _("Family %(id)s: %(descr)s") % {
'id': obj.get_gramps_id(),
'descr': name}, _("Cited in Family"))
'descr': name}, _("Cited in Family"), "Family")
def __add_event(self, obj, cite):
"""
@ -220,7 +276,7 @@ class CitedInTab(GrampsTab):
name = _('Event %(id)s: %(descr)s') % {
'id': obj.get_gramps_id(),
'descr': event_name}
self.__add_object(obj, cite, name, _("Cited in Event"))
self.__add_object(obj, cite, name, _("Cited in Event"), "Event")
def __add_place(self, obj, cite):
"""
@ -228,7 +284,7 @@ class CitedInTab(GrampsTab):
"""
self.__add_object(obj, cite, _('Place %(id)s: %(descr)s') % {
'id': obj.get_gramps_id(),
'descr': obj.get_title()}, _("Cited in Place"))
'descr': obj.get_title()}, _("Cited in Place"), "Place")
def __add_repo(self, obj, cite):
"""
@ -236,7 +292,7 @@ class CitedInTab(GrampsTab):
"""
self.__add_object(obj, cite, _('Repository %(id)s: %(descr)s') % {
'id': obj.get_gramps_id(),
'descr': obj.get_name()}, _("Cited in Repository"))
'descr': obj.get_name()}, _("Cited in Repository"), "Repository")
def __add_media(self, obj, cite):
"""
@ -249,7 +305,7 @@ class CitedInTab(GrampsTab):
name = obj.get_mime_type()
self.__add_object(obj, cite, _('Media %(id)s: %(descr)s') % {
'id': obj.get_gramps_id(),
'descr': name}, _("Cited in Media"))
'descr': name}, _("Cited in Media"), "Media")
def format_sec_obj(self, objsec):
"""
@ -302,53 +358,13 @@ class CitedInTab(GrampsTab):
'descr' : descr}
return descr
def setup_interface(self):
"""
Set all information on the widgets
* button tabs to load citation
* treeview in scrollable with info
"""
##print (self.srtdata)
##print(self.obj2citemap)
#create the load button, add it to a hbox, and add that box to the
#tab page
self.load_btn = SimpleButton(Gtk.STOCK_APPLY, self.load_button_clicked)
hbox = Gtk.HBox()
hbox.set_spacing(6)
hbox.pack_start(self.load_btn, False, True, 0)
hbox.show_all()
self.pack_start(hbox, False, True, 0)
if self.dbstate.db.readonly:
self.load_btn.set_sensitive(False)
# create the tree, turn on rule hinting and connect the
# button press to the double click function.
self.tree = Gtk.TreeView()
self.tree.set_rules_hint(True)
self.tree.connect('button_press_event', self.double_click)
self.tree.connect('key_press_event', self.key_pressed)
self.make_columns()
self.tree.set_model(self.model)
self.tree.expand_all()
# create the scrolled window, and attach the treeview
scroll = Gtk.ScrolledWindow()
scroll.set_shadow_type(Gtk.ShadowType.IN)
scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scroll.add(self.tree)
#add this to the tab
self.pack_start(scroll, True, True, 0)
def double_click(self, obj, event):
"""
Handles the double click on list. If the double click occurs,
the load button handler is called
the apply button handler is called
"""
if event.type == Gdk.EventType._2BUTTON_PRESS and event.button == 1:
self.load_button_clicked(obj)
self.apply_button_clicked(obj)
def key_pressed(self, obj, event):
"""
@ -358,48 +374,119 @@ class CitedInTab(GrampsTab):
if event.type == Gdk.EventType.KEY_PRESS:
#print 'key pressed', event.keyval, event.get_state(), _ADD
if event.keyval in (_RETURN, _KP_ENTER):
self.load_button_clicked(obj)
self.apply_button_clicked(obj)
return True
else:
return GrampsTab.key_pressed(self, obj, event)
return False
def load_button_clicked(self, obj):
def apply_button_clicked(self, obj):
"""
Function called with the Load button is clicked. This function
should be overridden by the derived class.
"""
print("Uncaught Add clicked")
sel = self.get_selected()
if sel[0]:
self.cite_apply_callback(sel[0])
def edit_button_clicked(self, obj):
"""
Function called with the Load button is clicked. This function
should be overridden by the derived class.
"""
sel = self.get_selected()
ref = sel[1]
reftype = sel[2]
if not ref:
return
from .. import (EditEvent, EditPerson, EditFamily, EditPlace,
EditMedia, EditRepository, EditCitation)
if reftype == 'Person':
try:
person = self.dbstate.db.get_person_from_handle(ref)
EditPerson(self.dbstate, self.uistate, [], person)
except WindowActiveError:
pass
elif reftype == 'Family':
try:
family = self.dbstate.db.get_family_from_handle(ref)
EditFamily(self.dbstate, self.uistate, [], family)
except WindowActiveError:
pass
elif reftype == 'Place':
try:
place = self.dbstate.db.get_place_from_handle(ref)
EditPlace(self.dbstate, self.uistate, [], place)
except WindowActiveError:
pass
elif reftype == 'Media':
try:
obj = self.dbstate.db.get_object_from_handle(ref)
EditMedia(self.dbstate, self.uistate, [], obj)
except WindowActiveError:
pass
elif reftype == 'Event':
try:
event = self.dbstate.db.get_event_from_handle(ref)
EditEvent(self.dbstate, self.uistate, [], event)
except WindowActiveError:
pass
elif reftype == 'Repository':
try:
repo = self.dbstate.db.get_repository_from_handle(ref)
EditRepository(self.dbstate, self.uistate, [], repo)
except WindowActiveError:
pass
def build_model(self):
"""
set up the model the treeview will use based on the data
"""
# store (citationhandle, primobjhandle, name, citationgid, index)
# store (citationhandle, primobjhandle, name, citationgid, index, classname)
# here, depending on the leve, name will be primobjname, secobjname, or
# subsecobjname
# citationhandle will be '' for rows which create sublevels
self.model = Gtk.TreeStore(str, str, str, str, int)
for (descr, primhandle, shortdescr) in self.srtdata:
self.model = Gtk.TreeStore(str, str, str, str, int, str)
if sys.version_info[0] < 3:
self.idle = GObject.idle_add(self.load_model().next)
else:
self.idle = GObject.idle_add(self.load_model().__next__)
def load_model(self):
"""
To make sure source editor is responsive, we use idle_add to
build the model.
WARNING: a consequence of above is that loading can still be happening
while the GUI using this model is no longer used. Disconnect any
methods before closing the GUI.
"""
for (descr, primhandle, shortdescr, objname) in self.srtdata:
data = self.obj2citemap[primhandle]
#top level node
iter = self.model.append(None, ['', primhandle, descr, '', -1])
iter = self.model.append(None, ['', primhandle, descr, '', -1, objname])
for ind, chandle in enumerate(data['prim']):
citation = self.dbstate.db.get_citation_from_handle(chandle)
self.model.append(iter, [chandle, primhandle, shortdescr,
citation.get_gramps_id(), ind])
citation.get_gramps_id(), ind, objname])
base = len(data['prim'])
for ind, val in enumerate(data['sec']):
chandle, secdescr = val
citation = self.dbstate.db.get_citation_from_handle(chandle)
self.model.append(iter, [chandle, primhandle, secdescr,
citation.get_gramps_id(), base+ind])
citation.get_gramps_id(), base+ind, objname])
base += len(data['sec'])
for ind, val in enumerate(data['subsec']):
chandle, subsecdescr = val
citation = self.dbstate.db.get_citation_from_handle(chandle)
self.model.append(iter, [chandle, primhandle, subsecdescr,
citation.get_gramps_id(), base+ind])
citation.get_gramps_id(), base+ind, objname])
yield True
#only now can we expand all nodes:
self.tree.expand_all()
yield False
def make_columns(self):
#make the columns in the treeview
@ -408,3 +495,18 @@ class CitedInTab(GrampsTab):
self.tree.append_column(column)
column = Gtk.TreeViewColumn(_("Citation"), renderer, text=3)
self.tree.append_column(column)
def get_selected(self):
"""
Return the (citation_handle, primary_object_handle, classname_prim_obj)
associated with the selected row in the model.
If no selection has been made, None is returned.
If not on a citation, citation_handle will be empty string ''
"""
(model, iter) = self.selection.get_selected()
# store contains: (citationhandle, primobjhandle, name, citationgid, index)
if iter:
return (model.get_value(iter, 0), model.get_value(iter, 1),
model.get_value(iter, 5))
return None

View File

@ -310,7 +310,7 @@ class EditSource(EditPrimary):
self.track_ref_for_deletion("attr_tab")
self.citedin_tab = CitedInTab(self.dbstate, self.uistate,
self.track, self.obj)
self.track, self.obj, self.cite_apply_callback)
self._add_tab(notebook, self.citedin_tab)
self.track_ref_for_deletion("citedin_tab")
@ -435,6 +435,22 @@ class EditSource(EditPrimary):
self.close()
# CITATION PART
def cite_apply_callback(self, citation_handle):
if self.citation:
self.unload_citation()
self.load_citation(citation_handle)
def unload_citation(self):
pass
def load_citation(self, chandle):
if self.citation:
raise Exception("Request to change citation, but another citation loaded")
self.citation = chandle
#update source part that uses citation
self.update_attr()
class DeleteSrcQuery(object):
def __init__(self, dbstate, uistate, source, the_lists):
self.source = source