2007-09-08 Benny Malengier <benny.malengier@gramps-project.org>
* src/DataViews/_RelationView.py : expand/collapse, edit button on/off bug fix * src/GrampsWidgets.py : Expand widget, changes link labels * src/DisplayState.py : history bugs * src/ViewManager.py : history bugs * src/PageView.py : history bugs Based on patch of Douglas S. Blank <dblank@cs.brynmawr.edu>, GEPS-2 Still some strange things in history, but better svn: r8950
This commit is contained in:
@ -1,3 +1,12 @@
|
||||
2007-09-08 Benny Malengier <benny.malengier@gramps-project.org>
|
||||
* src/DataViews/_RelationView.py : expand/collapse, edit button on/off bug fix
|
||||
* src/GrampsWidgets.py : Expand widget, changes link labels
|
||||
* src/DisplayState.py : history bugs
|
||||
* src/ViewManager.py : history bugs
|
||||
* src/PageView.py : history bugs
|
||||
Based on patch of Douglas S. Blank <dblank@cs.brynmawr.edu>, GEPS-2
|
||||
Still some strange things in history, but better
|
||||
|
||||
2007-09-07 Don Allingham <don@gramps-project.org>
|
||||
* various: const.py changes
|
||||
|
||||
|
@ -65,13 +65,13 @@ _GenderCode = {
|
||||
}
|
||||
|
||||
_NAME_START = 0
|
||||
_LABEL_START = 1
|
||||
_LABEL_STOP = 2
|
||||
_LABEL_START = 0
|
||||
_LABEL_STOP = 1
|
||||
_DATA_START = _LABEL_STOP
|
||||
_DATA_STOP = _DATA_START+1
|
||||
_BTN_START = _DATA_STOP
|
||||
_BTN_STOP = _BTN_START+2
|
||||
_PLABEL_START = 2
|
||||
_PLABEL_START = 1
|
||||
_PLABEL_STOP = _PLABEL_START+1
|
||||
_PDATA_START = _PLABEL_STOP
|
||||
_PDATA_STOP = _PDATA_START+2
|
||||
@ -83,12 +83,12 @@ _CDATA_START = _CLABEL_STOP
|
||||
_CDATA_STOP = _CDATA_START+1
|
||||
_CDTLS_START = _CDATA_START
|
||||
_CDTLS_STOP = _CDTLS_START+1
|
||||
_ALABEL_START = 1
|
||||
_ALABEL_START = 0
|
||||
_ALABEL_STOP = _ALABEL_START+1
|
||||
_ADATA_START = _ALABEL_STOP
|
||||
_ADATA_STOP = _ADATA_START+3
|
||||
_SDATA_START = 3
|
||||
_SDATA_STOP = 5
|
||||
_SDATA_START = 2
|
||||
_SDATA_STOP = 4
|
||||
|
||||
class AttachList:
|
||||
|
||||
@ -129,11 +129,12 @@ class RelationshipView(PageView.PersonNavView):
|
||||
|
||||
Config.client.notify_add("/apps/gramps/preferences/relation-shade",
|
||||
self.shade_update)
|
||||
Config.client.notify_add("/apps/gramps/interface/editbutton",
|
||||
Config.client.notify_add("/apps/gramps/interface/releditbtn",
|
||||
self.config_update)
|
||||
Config.client.notify_add("/apps/gramps/interface/toolbar-on",
|
||||
self.shade_update)
|
||||
self.reorder_sensitive = False
|
||||
self.collapsed_items = {}
|
||||
|
||||
def set_active(self):
|
||||
PageView.PersonNavView.set_active(self)
|
||||
@ -426,9 +427,9 @@ class RelationshipView(PageView.PersonNavView):
|
||||
if family_handle_list:
|
||||
for family_handle in family_handle_list:
|
||||
if family_handle:
|
||||
self.write_parents(family_handle)
|
||||
self.write_parents(family_handle, person)
|
||||
else:
|
||||
self.write_label("%s:" % _('Parents'), None, True)
|
||||
self.write_label("%s:" % _('Parents'), None, True, person)
|
||||
self.row += 1
|
||||
|
||||
family_handle_list = person.get_family_handle_list()
|
||||
@ -439,9 +440,9 @@ class RelationshipView(PageView.PersonNavView):
|
||||
if family_handle_list:
|
||||
for family_handle in family_handle_list:
|
||||
if family_handle:
|
||||
self.write_family(family_handle)
|
||||
self.write_family(family_handle, person)
|
||||
else:
|
||||
self.write_label("%s:" % _('Family'), None, False)
|
||||
self.write_label("%s:" % _('Family'), None, False, person)
|
||||
self.row += 1
|
||||
|
||||
self.row = 0
|
||||
@ -631,9 +632,26 @@ class RelationshipView(PageView.PersonNavView):
|
||||
self.row, self.row+1)
|
||||
self.row += 1
|
||||
|
||||
def write_label(self, title, family, is_parent):
|
||||
msg = "<i><b>%s</b></i>" % cgi.escape(title)
|
||||
self.attach.attach(GrampsWidgets.MarkupLabel(msg),
|
||||
def write_label(self, title, family, is_parent, person = None):
|
||||
msg = '<span style="italic" weight="heavy">%s</span>' % cgi.escape(title)
|
||||
hbox = gtk.HBox()
|
||||
label = GrampsWidgets.MarkupLabel(msg)
|
||||
# Draw the collapse/expand button:
|
||||
if family != None:
|
||||
if self.check_collapsed(person, family.handle):
|
||||
arrow = GrampsWidgets.ExpandCollapseArrow(True,
|
||||
self.expand_collapse_press,
|
||||
(person, family.handle))
|
||||
else:
|
||||
arrow = GrampsWidgets.ExpandCollapseArrow(False,
|
||||
self.expand_collapse_press,
|
||||
(person, family.handle))
|
||||
else :
|
||||
arrow = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_OUT)
|
||||
hbox.pack_start(arrow, False)
|
||||
|
||||
hbox.pack_start(label, False)
|
||||
self.attach.attach(hbox,
|
||||
_LABEL_START, _LABEL_STOP,
|
||||
self.row, self.row+1, gtk.SHRINK|gtk.FILL)
|
||||
|
||||
@ -645,6 +663,10 @@ class RelationshipView(PageView.PersonNavView):
|
||||
_DATA_START, _DATA_STOP,
|
||||
self.row, self.row+1, gtk.SHRINK|gtk.FILL)
|
||||
|
||||
if family and self.check_collapsed(person, family.handle):
|
||||
# show family names later
|
||||
pass
|
||||
else:
|
||||
hbox = gtk.HBox()
|
||||
hbox.set_spacing(12)
|
||||
if is_parent:
|
||||
@ -694,11 +716,47 @@ class RelationshipView(PageView.PersonNavView):
|
||||
|
||||
######################################################################
|
||||
|
||||
def write_parents(self, family_handle):
|
||||
def write_parents(self, family_handle, person = None):
|
||||
family = self.dbstate.db.get_family_from_handle(family_handle)
|
||||
if not family:
|
||||
return
|
||||
self.write_label("%s:" % _('Parents'), family, True)
|
||||
if person and self.check_collapsed(person, family_handle):
|
||||
# don't show rest
|
||||
self.write_label("%s:" % _('Parents'), family, True, person)
|
||||
self.row -= 1 # back up one row for summary names
|
||||
active = self.dbstate.active.handle
|
||||
child_list = [ref.ref for ref in family.get_child_ref_list()
|
||||
if ref.ref != active]
|
||||
if child_list:
|
||||
count = len(child_list)
|
||||
else:
|
||||
count = 0
|
||||
if count > 1 :
|
||||
childmsg = _(" (%d siblings)") % count
|
||||
elif count == 1 :
|
||||
gender = self.dbstate.db.get_person_from_handle(\
|
||||
child_list[0]).gender
|
||||
if gender == RelLib.Person.MALE :
|
||||
childmsg = _(" (1 brother)")
|
||||
elif gender == RelLib.Person.FEMALE :
|
||||
childmsg = _(" (1 sister)")
|
||||
else :
|
||||
childmsg = _(" (1 sibling)")
|
||||
else :
|
||||
childmsg = _(" (only child)")
|
||||
box = self.get_people_box(family.get_father_handle(),
|
||||
family.get_mother_handle(),
|
||||
post_msg=childmsg)
|
||||
eventbox = gtk.EventBox()
|
||||
if self.use_shade:
|
||||
eventbox.modify_bg(gtk.STATE_NORMAL, self.color)
|
||||
eventbox.add(box)
|
||||
self.attach.attach(
|
||||
eventbox, _PDATA_START, _PDATA_STOP,
|
||||
self.row, self.row+1)
|
||||
self.row += 1 # now advance it
|
||||
else:
|
||||
self.write_label("%s:" % _('Parents'), family, True, person)
|
||||
self.write_person(_('Father'), family.get_father_handle())
|
||||
self.write_person(_('Mother'), family.get_mother_handle())
|
||||
|
||||
@ -732,6 +790,39 @@ class RelationshipView(PageView.PersonNavView):
|
||||
|
||||
self.row += 1
|
||||
|
||||
def get_people_box(self, *handles, **kwargs):
|
||||
vbox = gtk.HBox()
|
||||
initial_name = True
|
||||
for handle in handles:
|
||||
if not initial_name:
|
||||
link_label = gtk.Label(" %s " % _('and'))
|
||||
link_label.show()
|
||||
vbox.pack_start(link_label, expand=False)
|
||||
initial_name = False
|
||||
if handle:
|
||||
name = self.get_name(handle, True)
|
||||
link_label = GrampsWidgets.LinkLabel(name,
|
||||
self.button_press, handle)
|
||||
if self.use_shade:
|
||||
link_label.modify_bg(gtk.STATE_NORMAL, self.color)
|
||||
if Config.get(Config.RELEDITBTN):
|
||||
button = GrampsWidgets.IconButton(self.edit_button_press,
|
||||
handle)
|
||||
self.tooltips.set_tip(button, _('Edit %s') % name[0])
|
||||
else:
|
||||
button = None
|
||||
vbox.pack_start(GrampsWidgets.LinkBox(link_label, button),
|
||||
expand=False)
|
||||
else:
|
||||
link_label = gtk.Label(_('Unknown'))
|
||||
link_label.show()
|
||||
vbox.pack_start(link_label, expand=False)
|
||||
if "post_msg" in kwargs and kwargs["post_msg"]:
|
||||
link_label = gtk.Label(kwargs["post_msg"])
|
||||
link_label.show()
|
||||
vbox.pack_start(link_label, expand=False)
|
||||
return vbox
|
||||
|
||||
def write_person(self, title, handle):
|
||||
if title:
|
||||
format = '<span weight="bold">%s: </span>'
|
||||
@ -793,8 +884,14 @@ class RelationshipView(PageView.PersonNavView):
|
||||
return lbl
|
||||
|
||||
def write_child(self, vbox, handle, index):
|
||||
parent = has_children(self.dbstate.db,
|
||||
self.dbstate.db.get_person_from_handle(handle))
|
||||
if parent:
|
||||
format = 'underline="single" weight="heavy" style="italic"'
|
||||
else:
|
||||
format = 'underline="single"'
|
||||
link_label = GrampsWidgets.LinkLabel(self.get_name(handle, True),
|
||||
self.button_press, handle)
|
||||
self.button_press, handle, format)
|
||||
if self.use_shade:
|
||||
link_label.modify_bg(gtk.STATE_NORMAL, self.color)
|
||||
link_label.set_padding(3, 0)
|
||||
@ -856,6 +953,27 @@ class RelationshipView(PageView.PersonNavView):
|
||||
value = ""
|
||||
return value
|
||||
|
||||
def check_collapsed(self, person, handle):
|
||||
""" Returns true if collapsed. """
|
||||
return (handle in self.collapsed_items.get(person.handle, []))
|
||||
|
||||
def expand_collapse_press(self, obj, event, pair):
|
||||
""" Calback function for ExpandCollapseArrow, user param is pair,
|
||||
which is a tuple (person, handle) with handle the section of which
|
||||
the collapse state must change, so a parent, siblings id,
|
||||
family id, family children id, etc
|
||||
"""
|
||||
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1:
|
||||
person, handle = pair
|
||||
if self.collapsed_items.has_key(person.handle):
|
||||
if handle in self.collapsed_items[person.handle]:
|
||||
self.collapsed_items[person.handle].remove(handle)
|
||||
else:
|
||||
self.collapsed_items[person.handle].append(handle)
|
||||
else:
|
||||
self.collapsed_items[person.handle] = [handle]
|
||||
self.redraw()
|
||||
|
||||
def button_press(self, obj, event, handle):
|
||||
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1:
|
||||
self.dbstate.change_active_handle(handle)
|
||||
@ -945,7 +1063,7 @@ class RelationshipView(PageView.PersonNavView):
|
||||
self.write_data(
|
||||
vbox, '%(event_type)s:' % value, start_col, stop_col)
|
||||
|
||||
def write_family(self, family_handle):
|
||||
def write_family(self, family_handle, person = None):
|
||||
family = self.dbstate.db.get_family_from_handle(family_handle)
|
||||
if family == None:
|
||||
from QuestionDialog import WarningDialog
|
||||
@ -961,7 +1079,34 @@ class RelationshipView(PageView.PersonNavView):
|
||||
else:
|
||||
handle = father_handle
|
||||
|
||||
self.write_label("%s:" % _('Family'), family, False)
|
||||
# collapse button
|
||||
if self.check_collapsed(person, family_handle):
|
||||
# show "> Family: ..." and nothing else
|
||||
self.write_label("%s:" % _('Family'), family, False, person)
|
||||
self.row -= 1 # back up
|
||||
child_list = family.get_child_ref_list()
|
||||
if child_list:
|
||||
count = len(child_list)
|
||||
else:
|
||||
count = 0
|
||||
if count > 1 :
|
||||
childmsg = _(" (%d children)") % count
|
||||
elif count == 1 :
|
||||
childmsg = _(" (1 child)")
|
||||
else :
|
||||
childmsg = _(" (no children)")
|
||||
box = self.get_people_box(handle, post_msg=childmsg)
|
||||
eventbox = gtk.EventBox()
|
||||
if self.use_shade:
|
||||
eventbox.modify_bg(gtk.STATE_NORMAL, self.color)
|
||||
eventbox.add(box)
|
||||
self.attach.attach(
|
||||
eventbox, _PDATA_START, _PDATA_STOP,
|
||||
self.row, self.row+1)
|
||||
self.row += 1 # now advance it
|
||||
else:
|
||||
# show "V Family: ..." and the rest
|
||||
self.write_label("%s:" % _('Family'), family, False, person)
|
||||
if handle:
|
||||
box = self.write_person(_('Spouse'), handle)
|
||||
|
||||
@ -990,7 +1135,6 @@ class RelationshipView(PageView.PersonNavView):
|
||||
self.attach.attach(
|
||||
eventbox, _CDATA_START, _CDATA_STOP, self.row,
|
||||
self.row+1)
|
||||
|
||||
self.row += 1
|
||||
|
||||
def edit_button_press(self, obj, event, handle):
|
||||
@ -1150,3 +1294,19 @@ class RelationshipView(PageView.PersonNavView):
|
||||
self.dbstate.active.handle)
|
||||
except Errors.WindowActiveError:
|
||||
pass
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Function to return if person has children
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def has_children(db,p):
|
||||
"""
|
||||
Returns if a person has children.
|
||||
"""
|
||||
for family_handle in p.get_family_handle_list():
|
||||
family = db.get_family_from_handle(family_handle)
|
||||
childlist = family.get_child_ref_list()
|
||||
if childlist and len(childlist) > 0:
|
||||
return True
|
||||
return False
|
||||
|
@ -64,6 +64,10 @@ DISABLED = -1
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class History(GrampsDb.GrampsDBCallback):
|
||||
""" History manages the objects of a certain type that have been viewed,
|
||||
with ability to go back, or forward.
|
||||
When accessing an object, it should be pushed on the History.
|
||||
"""
|
||||
|
||||
__signals__ = {
|
||||
'changed' : (list, ),
|
||||
@ -131,6 +135,17 @@ class History(GrampsDb.GrampsDBCallback):
|
||||
except IndexError:
|
||||
return u""
|
||||
|
||||
def present(self):
|
||||
'''return the person handle that is now active in the history
|
||||
'''
|
||||
try :
|
||||
if self.history :
|
||||
return self.history[self.index]
|
||||
else:
|
||||
return u""
|
||||
except IndexError:
|
||||
return u""
|
||||
|
||||
def at_end(self):
|
||||
return self.index+1 == len(self.history)
|
||||
|
||||
@ -315,8 +330,15 @@ class DisplayState(GrampsDb.GrampsDBCallback):
|
||||
else:
|
||||
return u""
|
||||
|
||||
def clear_history(self):
|
||||
def clear_history(self,handle=None):
|
||||
'''Clear the history. If handle is given, then the history is
|
||||
immediately initialized with a first entry
|
||||
(you'd eg want active person you view there as History contains the
|
||||
present object too!)
|
||||
'''
|
||||
self.phistory.clear()
|
||||
if handle :
|
||||
self.phistory.push(handle)
|
||||
|
||||
def set_busy_cursor(self, value):
|
||||
if value == self.busy:
|
||||
|
@ -87,14 +87,44 @@ hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)
|
||||
def realize_cb(widget):
|
||||
widget.window.set_cursor(hand_cursor)
|
||||
|
||||
class ExpandCollapseArrow(gtk.EventBox):
|
||||
"""
|
||||
Arrow to be used for expand/collapse of sections.
|
||||
Note: shadow does not work, we indicate action with realize_cb
|
||||
"""
|
||||
def __init__(self, collapsed, onbuttonpress, pair):
|
||||
"""
|
||||
Constructor for the ExpandCollapseArrow class.
|
||||
|
||||
@param collapsed: True if arrow must be shown collapsed,
|
||||
False otherwise
|
||||
@type collapsed: bool
|
||||
@param onbuttonpress: The callback function for button press
|
||||
@type onbuttonpress: callback
|
||||
@param pair: user param for onbuttonpress function
|
||||
"""
|
||||
gtk.EventBox.__init__(self)
|
||||
self.tooltips = gtk.Tooltips()
|
||||
if collapsed :
|
||||
self.arrow = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_OUT)
|
||||
self.tooltips.set_tip(self, _("Expand this section"))
|
||||
else:
|
||||
self.arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_OUT)
|
||||
self.tooltips.set_tip(self, _("Collapse this section"))
|
||||
|
||||
self.add(self.arrow)
|
||||
self.connect('button-press-event', onbuttonpress, pair)
|
||||
self.connect('realize', realize_cb)
|
||||
|
||||
class LinkLabel(gtk.EventBox):
|
||||
|
||||
def __init__(self, label, func, handle):
|
||||
def __init__(self, label, func, handle, decoration='underline="single"'):
|
||||
gtk.EventBox.__init__(self)
|
||||
self.orig_text = cgi.escape(label[0])
|
||||
self.gender = label[1]
|
||||
self.tooltips = gtk.Tooltips()
|
||||
text = '<span underline="single">%s</span>' % self.orig_text
|
||||
self.decoration = decoration
|
||||
text = '<span %s>%s</span>' % (self.decoration, self.orig_text)
|
||||
|
||||
msg = _('Click to make the active person\n'
|
||||
'Right click to display the edit menu')
|
||||
@ -110,7 +140,8 @@ class LinkLabel(gtk.EventBox):
|
||||
hbox = gtk.HBox()
|
||||
hbox.pack_start(self.label, False, False, 0)
|
||||
if label[1]:
|
||||
hbox.pack_start(GenderLabel(label[1]), False, False, 4)
|
||||
hbox.pack_start(GenderLabel(label[1]), False, False, 0)
|
||||
hbox.set_spacing(4)
|
||||
self.add(hbox)
|
||||
|
||||
self.connect('button-press-event', func, handle)
|
||||
@ -122,12 +153,12 @@ class LinkLabel(gtk.EventBox):
|
||||
self.label.set_padding(x, y)
|
||||
|
||||
def enter_text(self, obj, event, handle):
|
||||
text = '<span foreground="blue" underline="single">%s</span>' % self.orig_text
|
||||
text = '<span foreground="blue" %s>%s</span>' % (self.decoration, self.orig_text)
|
||||
self.label.set_text(text)
|
||||
self.label.set_use_markup(True)
|
||||
|
||||
def leave_text(self, obj, event, handle):
|
||||
text = '<span underline="single">%s</span>' % self.orig_text
|
||||
text = '<span %s>%s</span>' % (self.decoration, self.orig_text)
|
||||
self.label.set_text(text)
|
||||
self.label.set_use_markup(True)
|
||||
|
||||
|
@ -425,9 +425,11 @@ class PersonNavView(BookMarkView):
|
||||
def handle_history(self, handle):
|
||||
"""
|
||||
Updates the person history information
|
||||
It will push the person at the end of the history if that person is
|
||||
not present person
|
||||
"""
|
||||
hobj = self.uistate.phistory
|
||||
if handle and not hobj.lock:
|
||||
if handle and not hobj.lock and not (handle == hobj.present()):
|
||||
hobj.push(handle)
|
||||
self.fwd_action.set_sensitive(not hobj.at_end())
|
||||
self.back_action.set_sensitive(not hobj.at_front())
|
||||
|
@ -1003,7 +1003,11 @@ class ViewManager:
|
||||
def post_load(self):
|
||||
# This method is for the common UI post_load, both new files
|
||||
# and added data like imports.
|
||||
self.uistate.clear_history()
|
||||
if self.state.active :
|
||||
#clear history and fill history with first entry, active person
|
||||
self.uistate.clear_history(self.state.active.handle)
|
||||
else :
|
||||
self.uistate.clear_history(None)
|
||||
self.uistate.progress.hide()
|
||||
|
||||
self.state.db.undo_callback = self.change_undo_label
|
||||
|
Reference in New Issue
Block a user