Family context menu with quick reports

svn: r8897
This commit is contained in:
Benny Malengier 2007-08-30 19:49:04 +00:00
parent 8c8ba9eb9f
commit 824e44f63d
9 changed files with 958 additions and 766 deletions

View File

@ -6,6 +6,7 @@
* src/PageView.py : family quick reports * src/PageView.py : family quick reports
* src/plugins/all_events.py : a new quick report, family events * src/plugins/all_events.py : a new quick report, family events
* src/Simple/_SimpleAccess.py : add access to get_first_name * src/Simple/_SimpleAccess.py : add access to get_first_name
* src/glade/gramps.glade : eventbox on familyeditor
2007-08-30 Don Allingham <don@gramps-project.org> 2007-08-30 Don Allingham <don@gramps-project.org>
* src/GrampsDbUtils/_WriteGedcom.py (GedcomWriter.__write_person_name): fix * src/GrampsDbUtils/_WriteGedcom.py (GedcomWriter.__write_person_name): fix

View File

@ -38,6 +38,7 @@ import Bookmarks
import Errors import Errors
import Config import Config
from Filters.SideBar import FamilySidebarFilter from Filters.SideBar import FamilySidebarFilter
from ReportBase import CATEGORY_QR_FAMILY
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -67,6 +68,7 @@ class FamilyListView(PageView.ListView):
EDIT_MSG = _("Edit the selected family") EDIT_MSG = _("Edit the selected family")
DEL_MSG = _("Delete the selected family") DEL_MSG = _("Delete the selected family")
FILTER_TYPE = "Family" FILTER_TYPE = "Family"
QR_CATEGORY = CATEGORY_QR_FAMILY
def __init__(self, dbstate, uistate): def __init__(self, dbstate, uistate):
@ -146,6 +148,10 @@ class FamilyListView(PageView.ListView):
<menuitem action="Add"/> <menuitem action="Add"/>
<menuitem action="Edit"/> <menuitem action="Edit"/>
<menuitem action="Remove"/> <menuitem action="Remove"/>
<separator/>
<menu name="QuickReport" action="QuickReport">
<menuitem action="Dummy"/>
</menu>
</popup> </popup>
</ui>''' </ui>'''
@ -161,6 +167,13 @@ class FamilyListView(PageView.ListView):
self.add_action('FilterEdit', None, _('Family Filter Editor'), self.add_action('FilterEdit', None, _('Family Filter Editor'),
callback=self.filter_editor,) callback=self.filter_editor,)
self.all_action = gtk.ActionGroup(self.title + "/FamilyAll")
self.all_action.add_actions([
('QuickReport', None, _("Quick Report"), None, None, None),
('Dummy', None, ' ', None, None, self.dummy_report),
])
self.add_action_group(self.all_action)
def get_bookmarks(self): def get_bookmarks(self):
return self.dbstate.db.get_family_bookmarks() return self.dbstate.db.get_family_bookmarks()
@ -208,3 +221,10 @@ class FamilyListView(PageView.ListView):
EditFamily(self.dbstate, self.uistate, [], family) EditFamily(self.dbstate, self.uistate, [], family)
except Errors.WindowActiveError: except Errors.WindowActiveError:
pass pass
def dummy_report(self, obj):
''' For the xml UI definition of popup to work, the submenu
Quick Report must have an entry in the xml
As this submenu will be dynamically built, we offer a dummy action
'''
pass

View File

@ -62,6 +62,7 @@ from DisplayTabs import \
EmbeddedList,EventEmbedList,SourceEmbedList,FamilyAttrEmbedList,\ EmbeddedList,EventEmbedList,SourceEmbedList,FamilyAttrEmbedList,\
NoteTab,GalleryTab,FamilyLdsEmbedList, ChildModel NoteTab,GalleryTab,FamilyLdsEmbedList, ChildModel
from GrampsWidgets import * from GrampsWidgets import *
from ReportBase import CATEGORY_QR_FAMILY
import QuestionDialog import QuestionDialog
#from ObjectSelector import PersonSelector,PersonFilterSpec #from ObjectSelector import PersonSelector,PersonFilterSpec
@ -377,6 +378,8 @@ class FastFemaleFilter:
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
class EditFamily(EditPrimary): class EditFamily(EditPrimary):
QR_CATEGORY = CATEGORY_QR_FAMILY
def __init__(self,dbstate, uistate, track, family): def __init__(self,dbstate, uistate, track, family):
self.tooltips = gtk.Tooltips() self.tooltips = gtk.Tooltips()
@ -497,6 +500,9 @@ class EditFamily(EditPrimary):
self.mbox = self.top.get_widget('mbox') self.mbox = self.top.get_widget('mbox')
self.fbox = self.top.get_widget('fbox') self.fbox = self.top.get_widget('fbox')
#allow for a context menu
self.set_contexteventbox(self.top.get_widget("eventboxtop"))
def _connect_signals(self): def _connect_signals(self):
self.define_ok_button(self.top.get_widget('ok'), self.save) self.define_ok_button(self.top.get_widget('ok'), self.save)
self.define_cancel_button(self.top.get_widget('cancel')) self.define_cancel_button(self.top.get_widget('cancel'))

View File

@ -64,7 +64,7 @@ from DisplayTabs import \
PersonEventEmbedList,NameEmbedList,SourceEmbedList,AttrEmbedList,\ PersonEventEmbedList,NameEmbedList,SourceEmbedList,AttrEmbedList,\
AddrEmbedList,NoteTab,GalleryTab,WebEmbedList,PersonRefEmbedList, \ AddrEmbedList,NoteTab,GalleryTab,WebEmbedList,PersonRefEmbedList, \
LdsEmbedList,PersonBackRefList LdsEmbedList,PersonBackRefList
from QuickReports import create_quickreport_menu from ReportBase import CATEGORY_QR_PERSON
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -87,12 +87,12 @@ class EditPerson(EditPrimary):
""" """
use_patronymic = locale.getlocale(locale.LC_TIME)[0] in _use_patronymic use_patronymic = locale.getlocale(locale.LC_TIME)[0] in _use_patronymic
QR_CATEGORY = CATEGORY_QR_PERSON
def __init__(self, state, uistate, track, person, callback=None): def __init__(self, state, uistate, track, person, callback=None):
""" """
Creates an EditPerson window. Associates a person with the window. Creates an EditPerson window. Associates a person with the window.
""" """
print person, person.serialize()
EditPrimary.__init__(self, state, uistate, track, person, EditPrimary.__init__(self, state, uistate, track, person,
state.db.get_person_from_handle, callback) state.db.get_person_from_handle, callback)
@ -133,7 +133,7 @@ class EditPerson(EditPrimary):
self.obj_photo = self.top.get_widget("personPix") self.obj_photo = self.top.get_widget("personPix")
self.eventbox = self.top.get_widget("eventbox1") self.eventbox = self.top.get_widget("eventbox1")
self.contextbox = self.top.get_widget("eventboxtop") self.set_contexteventbox(self.top.get_widget("eventboxtop"))
def _post_init(self): def _post_init(self):
@ -164,8 +164,6 @@ class EditPerson(EditPrimary):
self.eventbox.connect('button-press-event', self.eventbox.connect('button-press-event',
self._image_button_press) self._image_button_press)
self.contextbox.connect('button-press-event',
self._contextmenu_button_press)
self._add_db_signal('family-rebuild', self.family_change) self._add_db_signal('family-rebuild', self.family_change)
self._add_db_signal('family-delete', self.family_change) self._add_db_signal('family-delete', self.family_change)
@ -468,37 +466,10 @@ class EditPerson(EditPrimary):
EditMediaRef(self.dbstate, self.uistate, self.track, EditMediaRef(self.dbstate, self.uistate, self.track,
media_obj, media_ref, self._image_callback) media_obj, media_ref, self._image_callback)
def _contextmenu_button_press(self, obj, event) : def _top_contextmenu(self):
""" '''override from base class, the menuitems and actiongroups for the
Button press event that is caught when a mousebutton has been top of context menu
pressed while on the table in the top part of the edit dialog '''
It opens a context menu with possible actions
"""
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
if self.obj.get_handle() == 0 :
return False
#build the possible popup menu
self._build_popup_ui()
if self.dbstate.db.get_default_person() and \
self.obj.get_handle() == \
self.dbstate.db.get_default_person().get_handle():
self.home_action.set_sensitive(False)
else :
self.home_action.set_sensitive(True)
menu = self.popupmanager.get_widget('/Popup')
if menu:
menu.popup(None, None, None, event.button, event.time)
return True
return False
def _build_popup_ui(self):
from ReportBase import CATEGORY_QR_PERSON
self.popupmanager = gtk.UIManager()
self.all_action = gtk.ActionGroup("/PersonAll") self.all_action = gtk.ActionGroup("/PersonAll")
self.home_action = gtk.ActionGroup("/PersonHome") self.home_action = gtk.ActionGroup("/PersonHome")
@ -511,31 +482,24 @@ class EditPerson(EditPrimary):
None, None, self._make_home_person), None, None, self._make_home_person),
]) ])
#see which quick reports are available now:
(ui, reportactions) = create_quickreport_menu(CATEGORY_QR_PERSON,
self.dbstate,self.obj.get_handle())
self.report_action = gtk.ActionGroup("/PersonReport")
self.report_action.add_actions(reportactions)
self.all_action.set_visible(True) self.all_action.set_visible(True)
self.home_action.set_visible(True) self.home_action.set_visible(True)
self.report_action.set_visible(True)
self.popupmanager.insert_action_group(self.all_action, -1) ui_top_cm = '''
self.popupmanager.insert_action_group(self.home_action, -1)
self.popupmanager.insert_action_group(self.report_action, -1)
popupui = '''
<ui>
<popup name="Popup">
<menuitem action="ActivePerson"/> <menuitem action="ActivePerson"/>
<menuitem action="HomePerson"/> <menuitem action="HomePerson"/>'''
<separator/>'''
self.popupmanager.add_ui_from_string(popupui + ui + ''' return ui_top_cm, [self.all_action, self.home_action]
</popup>
</ui>''') def _post_build_popup_ui(self):
'''override base class, make inactive home action if not needed
'''
if self.dbstate.db.get_default_person() and \
self.obj.get_handle() == \
self.dbstate.db.get_default_person().get_handle():
self.home_action.set_sensitive(False)
else :
self.home_action.set_sensitive(True)
def _make_active(self, obj): def _make_active(self, obj):
self.dbstate.change_active_person(self.obj) self.dbstate.change_active_person(self.obj)

View File

@ -21,6 +21,7 @@
# $Id$ # $Id$
from gettext import gettext as _ from gettext import gettext as _
import gtk
import ManagedWindow import ManagedWindow
import DateHandler import DateHandler
@ -31,6 +32,8 @@ from QuestionDialog import SaveDialog
class EditPrimary(ManagedWindow.ManagedWindow): class EditPrimary(ManagedWindow.ManagedWindow):
QR_CATEGORY = -1
def __init__(self, state, uistate, track, obj, get_from_handle, callback=None): def __init__(self, state, uistate, track, obj, get_from_handle, callback=None):
"""Creates an edit window. Associates a person with the window.""" """Creates an edit window. Associates a person with the window."""
@ -45,6 +48,7 @@ class EditPrimary(ManagedWindow.ManagedWindow):
self.signal_keys = [] self.signal_keys = []
self.ok_button = None self.ok_button = None
self.get_from_handle = get_from_handle self.get_from_handle = get_from_handle
self.contexteventbox = None
ManagedWindow.ManagedWindow.__init__(self, uistate, track, obj) ManagedWindow.ManagedWindow.__init__(self, uistate, track, obj)
@ -165,3 +169,76 @@ class EditPrimary(ManagedWindow.ManagedWindow):
def save(self,*obj): def save(self,*obj):
pass pass
def set_contexteventbox(self, eventbox):
'''Set the contextbox that grabs button presses if not grabbed
by overlying widgets.
'''
self.contexteventbox = eventbox
self.contexteventbox.connect('button-press-event',
self._contextmenu_button_press)
def _contextmenu_button_press(self, obj, event) :
"""
Button press event that is caught when a mousebutton has been
pressed while on contexteventbox
It opens a context menu with possible actions
"""
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3 :
if self.obj.get_handle() == 0 :
return False
#build the possible popup menu
self._build_popup_ui()
#set or unset sensitivity in popup
self._post_build_popup_ui()
menu = self.popupmanager.get_widget('/Popup')
if menu:
menu.popup(None, None, None, event.button, event.time)
return True
return False
def _build_popup_ui(self):
"""
Create actions and ui of context menu
"""
from QuickReports import create_quickreport_menu
self.popupmanager = gtk.UIManager()
#add custom actions
(ui_top, action_groups) = self._top_contextmenu()
for action in action_groups :
self.popupmanager.insert_action_group(action, -1)
#see which quick reports are available now:
ui_qr = ''
if self.QR_CATEGORY > -1 :
(ui_qr, reportactions) = create_quickreport_menu(self.QR_CATEGORY,
self.dbstate, self.obj.get_handle())
self.report_action = gtk.ActionGroup("/PersonReport")
self.report_action.add_actions(reportactions)
self.report_action.set_visible(True)
self.popupmanager.insert_action_group(self.report_action, -1)
popupui = '''
<ui>
<popup name="Popup">''' + ui_top + '''
<separator/>''' + ui_qr + '''
</popup>
</ui>'''
self.popupmanager.add_ui_from_string(popupui)
def _top_contextmenu(self):
"""
Derived class can create a ui with menuitems and corresponding list of
actiongroups
"""
return "",[]
def _post_build_popup_ui(self):
"""
Derived class should do extra actions here on the menu
"""
pass

View File

@ -47,6 +47,7 @@ import TreeTips
import Bookmarks import Bookmarks
import Errors import Errors
from Filters import SearchBar from Filters import SearchBar
import Utils
import const import const
NAVIGATION_NONE = -1 NAVIGATION_NONE = -1
@ -447,6 +448,7 @@ class ListView(BookMarkView):
ADD_MSG = "" ADD_MSG = ""
EDIT_MSG = "" EDIT_MSG = ""
DEL_MSG = "" DEL_MSG = ""
QR_CATEGORY = -1
def __init__(self, title, dbstate, uistate, columns, handle_col, def __init__(self, title, dbstate, uistate, columns, handle_col,
make_model, signal_map, get_bookmarks, bm_type, make_model, signal_map, get_bookmarks, bm_type,
@ -838,14 +840,35 @@ class ListView(BookMarkView):
pass pass
def button_press(self,obj,event): def button_press(self,obj,event):
from QuickReports import create_quickreport_menu
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1: if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
self.edit(obj) self.edit(obj)
return True return True
elif event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: elif event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
menu = self.uistate.uimanager.get_widget('/Popup') menu = self.uistate.uimanager.get_widget('/Popup')
#construct quick reports if needed
if menu and self.QR_CATEGORY>-1 :
qr_menu = self.uistate.uimanager.\
get_widget('/Popup/QuickReport').get_submenu()
if qr_menu :
self.uistate.uimanager.\
get_widget('/Popup/QuickReport').remove_submenu()
reportactions = []
if menu and self.dbstate.active:
(ui, reportactions) = create_quickreport_menu(
self.QR_CATEGORY,
self.dbstate,
self.first_selected())
if len(reportactions) > 1 :
qr_menu = gtk.Menu()
for action in reportactions[1:] :
Utils.add_menuitem(qr_menu, action[2], None, action[5])
self.uistate.uimanager.get_widget('/Popup/QuickReport').\
set_submenu(qr_menu)
if menu: if menu:
menu.popup(None, None, None, event.button, event.time) menu.popup(None, None, None, event.button, event.time)
return True return True
return False return False
def key_press(self,obj,event): def key_press(self,obj,event):

View File

@ -132,6 +132,21 @@ class SimpleAccess:
else: else:
return u'' return u''
def first_name(self, person):
"""
Returns the first name of the person, or and empty string if the person is None
@param person: Person object
@type person: L{RelLib.Person}
@return: Returns the first name of the person based of the program preferences
@rtype: unicode
"""
assert(isinstance(person, (RelLib.Person, NoneType)))
if person:
return person.get_primary_name().get_first_name()
else:
return u''
def gid(self, obj): def gid(self, obj):
""" """
Returns the GRAMPS ID of the person or family Returns the GRAMPS ID of the person or family

View File

@ -606,6 +606,12 @@
</packing> </packing>
</child> </child>
<child>
<widget class="GtkEventBox" id="eventboxtop">
<property name="visible">True</property>
<property name="visible_window">True</property>
<property name="above_child">False</property>
<child> <child>
<widget class="GtkVBox" id="vbox"> <widget class="GtkVBox" id="vbox">
<property name="border_width">6</property> <property name="border_width">6</property>
@ -1417,6 +1423,8 @@
</packing> </packing>
</child> </child>
</widget> </widget>
</child>
</widget>
<packing> <packing>
<property name="padding">0</property> <property name="padding">0</property>
<property name="expand">True</property> <property name="expand">True</property>

View File

@ -26,11 +26,13 @@ Display a person's events, both personal and family
from Simple import SimpleAccess, by_date, SimpleDoc from Simple import SimpleAccess, by_date, SimpleDoc
from gettext import gettext as _ from gettext import gettext as _
from PluginUtils import register_quick_report from PluginUtils import register_quick_report
from ReportBase import CATEGORY_QR_PERSON from ReportBase import CATEGORY_QR_PERSON, CATEGORY_QR_FAMILY
# define the formatting string once as a constant. Since this is reused # define the formatting string once as a constant. Since this is reused
__FMT = "%-15s\t%-15s\t%s" __FMT = "%-15s\t%-15s\t%s"
__FMT_fam = "%-15s\t%-15s\t%-15s\t%s"
def run(database, document, person): def run(database, document, person):
""" """
@ -65,6 +67,71 @@ def run(database, document, person):
sdb.event_date(event), sdb.event_date(event),
sdb.event_place(event))) sdb.event_place(event)))
def run_fam(database, document, family):
"""
Loops through the family events and the events of all parents, displaying
the basic details of the event
"""
sdb = SimpleAccess(database)
sdoc = SimpleDoc(document)
# get the family events
event_list = [(_('Family'), x) for x in sdb.events(family)]
# get the events of father and mother
fathername = sdb.first_name(sdb.father(family))
event_list += [(fathername, x) for x in sdb.events(sdb.father(family))]
mothername = sdb.first_name(sdb.mother(family))
event_list += [(mothername, x) for x in sdb.events(sdb.mother(family))]
# children events
event_list_children = []
for child in sdb.children(family) :
name = sdb.first_name(child)
event_list_children += [(name, x) for x in sdb.events(child)]
# Sort the events by their date
event_list.sort(fam_sort)
event_list_children.sort(fam_sort)
# display the results
sdoc.title(_("Sorted events of family\n %s - %s") %
(sdb.name(sdb.father(family)),
sdb.name(sdb.mother(family))))
sdoc.paragraph("")
sdoc.header2(__FMT_fam % (_("Family Member"), _("Event Type"),
_("Event Date"), _("Event Place")))
for (name, event) in event_list:
sdoc.paragraph(__FMT_fam % (name, sdb.event_type(event),
sdb.event_date(event),
sdb.event_place(event)))
sdoc.paragraph("")
sdoc.header1(_("Personal events of the children"))
sdoc.header2(__FMT_fam % (_("Family Member"), _("Event Type"),
_("Event Date"), _("Event Place")))
for (name, event) in event_list_children:
sdoc.paragraph(__FMT_fam % (name, sdb.event_type(event),
sdb.event_date(event),
sdb.event_place(event)))
def fam_sort(event1, event2):
"""
Sort function that will compare two events by their dates.
@param event1: first event
@type event1: L{Event}
@param event2: second event
@type event2: L{Event}
@return: Returns -1 if event1 < event2, 0 if they are equal, and
1 if they are the same.
@rtype: int
"""
return by_date(event1[1],event2[1])
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# #
@ -80,3 +147,14 @@ register_quick_report(
author_name="Donald N. Allingham", author_name="Donald N. Allingham",
author_email="don@gramps-project.org" author_email="don@gramps-project.org"
) )
register_quick_report(
name = 'all_events_fam',
category = CATEGORY_QR_FAMILY,
run_func = run_fam,
translated_name = _("All Events"),
status = _("Stable"),
description= _("Display the family and family members events."),
author_name="B. Malengier",
author_email="benny.malengier@gramps-project.org"
)