3093: Enable grouped displaytab in the editor: Name tab
svn: r12781
This commit is contained in:
parent
d49e1f0ec7
commit
2a685cbd7a
@ -282,6 +282,7 @@ src/DisplayTabs/_FamilyAttrEmbedList.py
|
||||
src/DisplayTabs/_FamilyLdsEmbedList.py
|
||||
src/DisplayTabs/_GalleryTab.py
|
||||
src/DisplayTabs/_GrampsTab.py
|
||||
src/DisplayTabs/_GroupEmbeddedList.py
|
||||
src/DisplayTabs/_LdsEmbedList.py
|
||||
src/DisplayTabs/_LdsModel.py
|
||||
src/DisplayTabs/_LocationEmbedList.py
|
||||
|
@ -21,6 +21,7 @@ pkgdata_PYTHON = \
|
||||
_FamilyLdsEmbedList.py \
|
||||
_GalleryTab.py \
|
||||
_GrampsTab.py \
|
||||
_GroupEmbeddedList.py \
|
||||
_LdsEmbedList.py \
|
||||
_LdsModel.py \
|
||||
_LocationEmbedList.py \
|
||||
|
@ -65,12 +65,14 @@ class AddrEmbedList(EmbeddedList):
|
||||
'down' : _('Move the selected address downwards'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Date'), 0, 150),
|
||||
(_('Address'), 1, 225),
|
||||
(_('City'), 2, 100),
|
||||
(_('State'), 3, 100),
|
||||
(_('Country'), 4, 75),
|
||||
(_('Date'), 0, 150, 1, -1),
|
||||
(_('Address'), 1, 225, 0, -1),
|
||||
(_('City'), 2, 100, 0, -1),
|
||||
(_('State'), 3, 100, 0, -1),
|
||||
(_('Country'), 4, 75, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data):
|
||||
|
@ -56,9 +56,11 @@ class AttrEmbedList(EmbeddedList):
|
||||
'down' : _('Move the selected attribute downwards'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Type'), 0, 250),
|
||||
(_('Value'), 1, 200),
|
||||
(_('Type'), 0, 250, 0, -1),
|
||||
(_('Value'), 1, 200, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data):
|
||||
|
@ -53,10 +53,12 @@ class BackRefList(EmbeddedList):
|
||||
|
||||
_HANDLE_COL = 3
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Type'), 0, 100),
|
||||
(_('ID'), 1, 75),
|
||||
(_('Name'), 2, 250),
|
||||
(_('Type'), 0, 100, 0, -1),
|
||||
(_('ID'), 1, 75, 0, -1),
|
||||
(_('Name'), 2, 250, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, obj, refmodel, callback=None):
|
||||
|
@ -53,9 +53,11 @@ class DataEmbedList(EmbeddedList):
|
||||
'down' : _('Move the selected data entry downwards'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text
|
||||
_column_names = [
|
||||
(_('Key'), 0, 150),
|
||||
(_('Value'), 1, 250),
|
||||
(_('Key'), 0, 150, 0, -1),
|
||||
(_('Value'), 1, 250, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, obj):
|
||||
|
@ -2,6 +2,7 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -100,7 +101,7 @@ class EmbeddedList(ButtonTab):
|
||||
elif event.type == gtk.gdk.BUTTON_PRESS and event.button == 2:
|
||||
fun = self.get_middle_click()
|
||||
if fun:
|
||||
fun(obj)
|
||||
fun()
|
||||
|
||||
def get_popup_menu_items(self):
|
||||
"""
|
||||
@ -182,6 +183,7 @@ class EmbeddedList(ButtonTab):
|
||||
self.tree.connect('drag_data_get', self.drag_data_get)
|
||||
if not self.dbstate.db.readonly:
|
||||
self.tree.connect('drag_data_received', self.drag_data_received)
|
||||
self.tree.connect('drag_motion', self.tree_drag_motion)
|
||||
|
||||
def drag_data_get(self, widget, context, sel_data, info, time):
|
||||
"""
|
||||
@ -237,6 +239,13 @@ class EmbeddedList(ButtonTab):
|
||||
elif self._DND_EXTRA and mytype == self._DND_EXTRA.drag_type:
|
||||
self.handle_extra_type(mytype, obj)
|
||||
|
||||
def tree_drag_motion(self, *args):
|
||||
"""
|
||||
On drag motion one wants the list to show as the database
|
||||
representation so it is clear how save will change the data
|
||||
"""
|
||||
pass
|
||||
|
||||
def handle_extra_type(self, objtype, obj):
|
||||
pass
|
||||
|
||||
@ -419,13 +428,18 @@ class EmbeddedList(ButtonTab):
|
||||
name = self._column_names[pair[1]][0]
|
||||
renderer = gtk.CellRendererText()
|
||||
renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
|
||||
if name == _("Date"):
|
||||
column = gtk.TreeViewColumn(name, renderer, markup=pair[1])
|
||||
else:
|
||||
if self._column_names[pair[1]][3] == 0:
|
||||
column = gtk.TreeViewColumn(name, renderer, text=pair[1])
|
||||
else:
|
||||
column = gtk.TreeViewColumn(name, renderer, markup=pair[1])
|
||||
if not self._column_names[pair[1]][4] == -1:
|
||||
#apply weight attribute
|
||||
column.add_attribute(renderer, "weight",
|
||||
self._column_names[pair[1]][4])
|
||||
|
||||
# insert the colum into the tree
|
||||
column.set_resizable(True)
|
||||
column.set_clickable(True)
|
||||
column.set_min_width(self._column_names[pair[1]][2])
|
||||
column.set_sort_column_id(self._column_names[pair[1]][1])
|
||||
self.columns.append(column)
|
||||
@ -453,3 +467,7 @@ class EmbeddedList(ButtonTab):
|
||||
#model and tree are reset, allow _selection_changed again, and force it
|
||||
self.dirty_selection = False
|
||||
self._selection_changed()
|
||||
self.post_rebuild()
|
||||
|
||||
def post_rebuild(self):
|
||||
pass
|
||||
|
@ -58,13 +58,15 @@ class EventEmbedList(EmbeddedList):
|
||||
'down' : _('Move the selected event downwards'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Type'), 0, 100),
|
||||
(_('Description'), 1, 175),
|
||||
(_('ID'), 2, 60),
|
||||
(_('Date'), 6, 150),
|
||||
(_('Place'), 4, 140),
|
||||
(_('Role'), 5, 80),
|
||||
(_('Type'), 0, 100, 0, -1),
|
||||
(_('Description'), 1, 175, 0, -1),
|
||||
(_('ID'), 2, 60, 0, -1),
|
||||
(_('Date'), 6, 150, 1, -1),
|
||||
(_('Place'), 4, 140, 0, -1),
|
||||
(_('Role'), 5, 80, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, obj):
|
||||
|
@ -45,12 +45,14 @@ class FamilyLdsEmbedList(LdsEmbedList):
|
||||
_HANDLE_COL = 5
|
||||
# _DND_TYPE = DdTargets.ADDRESS
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Type'), 0, 150),
|
||||
(_('Date'), 1, 150),
|
||||
(_('Status'), 3, 75),
|
||||
(_('Temple'), 2, 200),
|
||||
(_('Place'), 3, 100),
|
||||
(_('Type'), 0, 150, 0, -1),
|
||||
(_('Date'), 1, 150, 1, -1),
|
||||
(_('Status'), 3, 75, 0, -1),
|
||||
(_('Temple'), 2, 200, 0, -1),
|
||||
(_('Place'), 3, 100, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data):
|
||||
|
348
src/DisplayTabs/_GroupEmbeddedList.py
Normal file
348
src/DisplayTabs/_GroupEmbeddedList.py
Normal file
@ -0,0 +1,348 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# python
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
import cPickle as pickle
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK libraries
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
import pango
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from DisplayTabs._EmbeddedList import EmbeddedList
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class GroupEmbeddedList(EmbeddedList):
|
||||
"""
|
||||
This class provides the base class for all the list tabs that show
|
||||
grouped data.
|
||||
|
||||
It maintains a gtk.TreeView, including the selection and button sensitivity.
|
||||
"""
|
||||
|
||||
_CANDRAGGROUP = []
|
||||
_WORKGROUP = 0
|
||||
|
||||
def __init__(self, dbstate, uistate, track, name, build_model,
|
||||
share_button=False, move_buttons=False, jump_button=False):
|
||||
"""
|
||||
Create a new list, using the passed build_model to populate the list.
|
||||
"""
|
||||
EmbeddedList.__init__(self, dbstate, uistate, track, name, build_model,
|
||||
share_button, move_buttons, jump_button)
|
||||
#connect click on the first column
|
||||
self.columns[0].connect('clicked', self.groupcol_click)
|
||||
for col in self.columns[1:]:
|
||||
col.connect('clicked', self.col_click)
|
||||
self.dbsort = True
|
||||
|
||||
def groupcol_click(self, obj):
|
||||
"""
|
||||
The group column is clicked, sort it as it was
|
||||
"""
|
||||
self.columns[0].set_sort_order(gtk.SORT_ASCENDING)
|
||||
self.rebuild()
|
||||
self.dbsort = True
|
||||
|
||||
def col_click(self, obj):
|
||||
self.dbsort = False
|
||||
|
||||
def _on_button_press(self, obj, event):
|
||||
"""
|
||||
Handle button press, not double-click, that is done in init_interface
|
||||
"""
|
||||
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
|
||||
obj = self.get_selected()
|
||||
if obj and obj[1]:
|
||||
self._tmpgroup = obj[0]
|
||||
self.right_click(obj[1], event)
|
||||
elif event.type == gtk.gdk.BUTTON_PRESS and event.button == 2:
|
||||
fun = self.get_middle_click()
|
||||
if fun:
|
||||
fun()
|
||||
|
||||
def is_empty(self):
|
||||
"""
|
||||
Return True if the get_data returns a length greater than
|
||||
0. Typically, get_data returns the list of associated data.
|
||||
"""
|
||||
return len(self.get_data()[self._WORKGROUP]) == 0
|
||||
|
||||
def drag_data_get(self, widget, context, sel_data, info, time):
|
||||
"""
|
||||
Provide the drag_data_get function, which passes a tuple consisting of:
|
||||
|
||||
1) Drag type defined by the .drag_type field specfied by the value
|
||||
assigned to _DND_TYPE
|
||||
2) The id value of this object, used for the purpose of determining
|
||||
the source of the object. If the source of the object is the same
|
||||
as the object, we are doing a reorder instead of a normal drag
|
||||
and drop
|
||||
3) Pickled data. The pickled version of the selected object
|
||||
4) Source row. Used for a reorder to determine the original position
|
||||
of the object
|
||||
"""
|
||||
|
||||
# get the selected object, returning if not is defined
|
||||
obj = self.get_selected()
|
||||
if not obj or obj[1] is None:
|
||||
#nothing selected or a grouping selected
|
||||
return
|
||||
if not obj[0] in self._CANDRAGGROUP:
|
||||
return
|
||||
|
||||
# pickle the data, and build the tuple to be passed
|
||||
value = (self._DND_TYPE.drag_type, id(self), obj[1],
|
||||
self.find_index(obj))
|
||||
data = pickle.dumps(value)
|
||||
|
||||
# pass as a string (8 bits)
|
||||
sel_data.set(sel_data.target, 8, data)
|
||||
|
||||
def drag_data_received(self, widget, context, x, y, sel_data, info, time):
|
||||
"""
|
||||
Handle the standard gtk interface for drag_data_received.
|
||||
|
||||
If the selection data is define, extract the value from sel_data.data,
|
||||
and decide if this is a move or a reorder.
|
||||
"""
|
||||
if sel_data and sel_data.data:
|
||||
(mytype, selfid, obj, row_from) = pickle.loads(sel_data.data)
|
||||
|
||||
# make sure this is the correct DND type for this object
|
||||
if mytype == self._DND_TYPE.drag_type:
|
||||
|
||||
# determine the destination row
|
||||
row = self._find_row(x, y)
|
||||
|
||||
# if this is same object, we have a move, otherwise,
|
||||
# it is a standard drag-n-drop
|
||||
|
||||
if id(self) == selfid and self.get_selected() is not None:
|
||||
self._move(row_from, row, obj)
|
||||
else:
|
||||
self._handle_drag(row, obj)
|
||||
self.rebuild()
|
||||
elif self._DND_EXTRA and mytype == self._DND_EXTRA.drag_type:
|
||||
self.handle_extra_type(mytype, obj)
|
||||
|
||||
def tree_drag_motion(self, *args):
|
||||
"""
|
||||
On drag motion one wants the list to show as the database
|
||||
representation so it is clear how save will change the data
|
||||
"""
|
||||
if not self.dbsort:
|
||||
self.columns[0].clicked()
|
||||
|
||||
def find_index(self, obj):
|
||||
"""
|
||||
Returns the index of the object within the associated data.
|
||||
This will be a path (groupindex, index)
|
||||
"""
|
||||
data = self.get_data()
|
||||
groupindex = None
|
||||
index = None
|
||||
for groupindex, group in enumerate(data):
|
||||
try:
|
||||
index = group.index(obj[1])
|
||||
break
|
||||
except ValueError:
|
||||
pass
|
||||
return (groupindex, index)
|
||||
|
||||
def _find_row(self, x, y):
|
||||
"""
|
||||
Return a path as [groupindex, index] of the row on x,y.
|
||||
If no row, then a new line in the working group is returned
|
||||
"""
|
||||
dest = self.tree.get_dest_row_at_pos(x, y)
|
||||
if dest is None:
|
||||
if self.is_empty():
|
||||
return [self._WORKGROUP, 0]
|
||||
else:
|
||||
return [self._WORKGROUP, len(self.get_data()[self._WORKGROUP])]
|
||||
else:
|
||||
row = dest[0]
|
||||
if len(row) == 1:
|
||||
#drop on a group node, change to first real row
|
||||
row = (row[0], 0)
|
||||
return row
|
||||
|
||||
def _handle_drag(self, row, obj):
|
||||
"""
|
||||
drag from external place to row of obj
|
||||
"""
|
||||
if row[0] == self._WORKGROUP:
|
||||
self.get_data()[self._WORKGROUP].insert(row[1], obj)
|
||||
self.changed = True
|
||||
self.rebuild()
|
||||
else:
|
||||
self.dropnotworkgroup(row, obj)
|
||||
|
||||
def dropnotworkgroup(self, row, obj):
|
||||
"""
|
||||
Drop of obj on row that is not WORKGROUP
|
||||
"""
|
||||
pass
|
||||
|
||||
def _move(self, row_from, row_to, obj):
|
||||
"""
|
||||
Drag and drop move of the order. Allow in workgroup
|
||||
"""
|
||||
if row_from[0] == row_to[0] and row_from[0] == self._WORKGROUP:
|
||||
dlist = self.get_data()[self._WORKGROUP]
|
||||
if row_from[1] < row_to[1]:
|
||||
dlist.insert(row_to[1], obj)
|
||||
del dlist[row_from[1]]
|
||||
else:
|
||||
del dlist[row_from[1]]
|
||||
dlist.insert(row_to[1]-1, obj)
|
||||
self.changed = True
|
||||
self.rebuild()
|
||||
elif row_from[0] == self._WORKGROUP:
|
||||
self.move_away_work(row_from, row_to, obj)
|
||||
elif row_to[0] == self._WORKGROUP:
|
||||
self.move_to_work(row_from, row_to, obj)
|
||||
|
||||
def move_away_work(self, row_from, row_to, obj):
|
||||
"""
|
||||
move from the workgroup to a not workgroup
|
||||
handle in inherited class, default is nothing changes
|
||||
"""
|
||||
pass
|
||||
|
||||
def move_to_work(self, row_from, row_to, obj):
|
||||
"""
|
||||
move from a non workgroup to the workgroup
|
||||
handle in inherited class, default is nothing changes
|
||||
"""
|
||||
pass
|
||||
|
||||
def _move_up(self, row_from, obj, selmethod=None):
|
||||
"""
|
||||
Move the item a position up in the EmbeddedList.
|
||||
Eg: 0,1,2,3 needs to become 0,2,1,3, here row_from = 2
|
||||
"""
|
||||
if row_from[0] == self._WORKGROUP:
|
||||
if selmethod :
|
||||
dlist = selmethod()
|
||||
else :
|
||||
dlist = self.get_data()[self._WORKGROUP]
|
||||
del dlist[row_from[1]]
|
||||
dlist.insert(row_from[1]-1, obj)
|
||||
self.changed = True
|
||||
self.rebuild()
|
||||
#select the row
|
||||
self.tree.get_selection().select_path((self._WORKGROUP,
|
||||
row_from[1]-1))
|
||||
else:
|
||||
self._move_up_notwork(row_from, obj, selmethod)
|
||||
|
||||
def _move_up_notwork(self, row_from, obj, selmethod=None):
|
||||
"""
|
||||
move up outside of workgroup
|
||||
"""
|
||||
pass
|
||||
|
||||
def _move_down(self, row_from, obj, selmethod=None):
|
||||
"""
|
||||
Move the item a position down in the EmbeddedList.
|
||||
Eg: 0,1,2,3 needs to become 0,2,1,3, here row_from = 1
|
||||
"""
|
||||
if row_from[0] == self._WORKGROUP:
|
||||
if selmethod :
|
||||
dlist = selmethod()
|
||||
else :
|
||||
dlist = self.get_data()[self._WORKGROUP]
|
||||
del dlist[row_from[1]]
|
||||
dlist.insert(row_from[1]+1, obj)
|
||||
self.changed = True
|
||||
self.rebuild()
|
||||
#select the row
|
||||
self.tree.get_selection().select_path((self._WORKGROUP,
|
||||
row_from[1]+1))
|
||||
else:
|
||||
self._move_down_notwork(row_from, obj, selmethod)
|
||||
|
||||
def _move_down_notwork(self, row_from, obj, selmethod=None):
|
||||
"""
|
||||
move down outside of workgroup
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_icon_name(self):
|
||||
"""
|
||||
Specifies the basic icon used for a generic list. Typically,
|
||||
a derived class will override this. The icon chosen is the
|
||||
STOCK_JUSTIFY_FILL icon, which in the default GTK style
|
||||
looks kind of like a list.
|
||||
"""
|
||||
return gtk.STOCK_JUSTIFY_FILL
|
||||
|
||||
def del_button_clicked(self, obj):
|
||||
ref = self.get_selected()
|
||||
if ref and ref[1] is not None:
|
||||
if ref[0]==self._WORKGROUP:
|
||||
ref_list = self.get_data()[self._WORKGROUP]
|
||||
ref_list.remove(ref[1])
|
||||
self.changed = True
|
||||
self.rebuild()
|
||||
else:
|
||||
self.del_notwork(ref)
|
||||
|
||||
def del_notwork(self, ref):
|
||||
"""
|
||||
delete of ref asked that is not part of workgroup
|
||||
"""
|
||||
pass
|
||||
|
||||
def up_button_clicked(self, obj):
|
||||
ref = self.get_selected()
|
||||
if ref and ref[1] is not None:
|
||||
pos = self.find_index(ref)
|
||||
if pos[1] > 0 :
|
||||
self._move_up(pos, ref[1])
|
||||
|
||||
def down_button_clicked(self, obj):
|
||||
ref = self.get_selected()
|
||||
if ref and ref[1] is not None:
|
||||
pos = self.find_index(ref)
|
||||
if pos[1] >=0 and pos[1] < len(self.get_data()[pos[0]])-1:
|
||||
self._move_down(pos, ref[1])
|
@ -55,12 +55,14 @@ class LdsEmbedList(EmbeddedList):
|
||||
'down' : _('Move the selected LDS ordinance downwards'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Type'), 0, 150),
|
||||
(_('Date'), 1, 150),
|
||||
(_('Status'), 3, 75),
|
||||
(_('Temple'), 2, 200),
|
||||
(_('Place'), 3, 100),
|
||||
(_('Type'), 0, 150, 0, -1),
|
||||
(_('Date'), 1, 150, 1, -1),
|
||||
(_('Status'), 3, 75, 0, -1),
|
||||
(_('Temple'), 2, 200, 0, -1),
|
||||
(_('Place'), 3, 100, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data):
|
||||
|
@ -48,12 +48,14 @@ class LocationEmbedList(EmbeddedList):
|
||||
_HANDLE_COL = 5
|
||||
_DND_TYPE = DdTargets.LOCATION
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Street'), 0, 150),
|
||||
(_('City'), 1, 100),
|
||||
(_('County'), 2, 100),
|
||||
(_('State/Province'), 3, 100),
|
||||
(_('Country'), 4, 75),
|
||||
(_('Street'), 0, 150, 0, -1),
|
||||
(_('City'), 1, 100, 0, -1),
|
||||
(_('County'), 2, 100, 0, -1),
|
||||
(_('State/Province'), 3, 100, 0, -1),
|
||||
(_('Country'), 4, 75, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data):
|
||||
|
@ -2,6 +2,7 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# 2009 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -43,17 +44,19 @@ import gen.lib
|
||||
import Errors
|
||||
from DdTargets import DdTargets
|
||||
from DisplayTabs._NameModel import NameModel
|
||||
from DisplayTabs._EmbeddedList import EmbeddedList
|
||||
from DisplayTabs._GroupEmbeddedList import GroupEmbeddedList
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class NameEmbedList(EmbeddedList):
|
||||
class NameEmbedList(GroupEmbeddedList):
|
||||
|
||||
_HANDLE_COL = 2
|
||||
_DND_TYPE = DdTargets.NAME
|
||||
_CANDRAGGROUP = [NameModel._DEFINDEX, NameModel._ALTINDEX]
|
||||
_WORKGROUP = NameModel._ALTINDEX
|
||||
|
||||
_MSG = {
|
||||
'add' : _('Create and add a new name'),
|
||||
@ -63,9 +66,16 @@ class NameEmbedList(EmbeddedList):
|
||||
'down' : _('Move the selected name downwards'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Name'), 0, 250),
|
||||
(_('Type'), 1, 100),
|
||||
(_('Name'), -1, 250, 0, NameModel.COL_FONTWEIGHT[0]),
|
||||
(_('Type'), NameModel.COL_TYPE[0], 100, 0, -1),
|
||||
None,
|
||||
None,
|
||||
(_('Group As'), NameModel.COL_GROUPAS[0],100, 0, -1),
|
||||
(_('Source'), NameModel.COL_HASSOURCE[0],60, 0, -1),
|
||||
(_('Note Preview'), NameModel.COL_NOTEPREVIEW[0], 250, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data, person, callback):
|
||||
@ -73,33 +83,62 @@ class NameEmbedList(EmbeddedList):
|
||||
self.person = person
|
||||
self.callback = callback
|
||||
|
||||
EmbeddedList.__init__(self, dbstate, uistate, track, _('_Names'),
|
||||
GroupEmbeddedList.__init__(self, dbstate, uistate, track, _('_Names'),
|
||||
NameModel, move_buttons=True)
|
||||
self.tree.expand_all()
|
||||
|
||||
def get_data(self):
|
||||
return self.data
|
||||
return ([self.person.get_primary_name()],
|
||||
self.data)
|
||||
|
||||
def column_order(self):
|
||||
return ((1, 0), (1, 1))
|
||||
"""
|
||||
The columns to show as a tuple of tuples containing
|
||||
tuples (show/noshow, model column)
|
||||
"""
|
||||
return ((1, 0), (1, 1), (1, 4), (1, 5), (1, 6))
|
||||
|
||||
def get_popup_menu_items(self):
|
||||
if self._tmpgroup == self._WORKGROUP:
|
||||
return [
|
||||
(True, True, gtk.STOCK_ADD, self.add_button_clicked),
|
||||
(False,True, gtk.STOCK_EDIT, self.edit_button_clicked),
|
||||
(True, True, gtk.STOCK_REMOVE, self.del_button_clicked),
|
||||
(True, False, _('Set as default name'), self.name_button_clicked),
|
||||
]
|
||||
else:
|
||||
return [
|
||||
(True, True, gtk.STOCK_ADD, self.add_button_clicked),
|
||||
(False,True, gtk.STOCK_EDIT, self.edit_button_clicked),
|
||||
]
|
||||
|
||||
def name_button_clicked(self, obj):
|
||||
name = self.get_selected()
|
||||
if name and name[1]:
|
||||
self.set_default_name(name[1])
|
||||
|
||||
def set_default_name(self, name):
|
||||
pname = self.person.get_primary_name()
|
||||
if name:
|
||||
self.person.set_primary_name(name)
|
||||
self.data.remove(name)
|
||||
remove = []
|
||||
for altname in self.data:
|
||||
if altname.is_equal(name):
|
||||
remove.append(altname)
|
||||
for altname in remove:
|
||||
self.data.remove(altname)
|
||||
#only non empty name should move to alternative names
|
||||
if not name.is_equal(gen.lib.Name()):
|
||||
self.data.append(pname)
|
||||
self.rebuild()
|
||||
self.callback()
|
||||
|
||||
def update_defname(self):
|
||||
"""
|
||||
callback from person editor if change to the preferred name happens
|
||||
"""
|
||||
self.model.update_defname(self.person.get_primary_name())
|
||||
self.tree.expand_all()
|
||||
|
||||
def add_button_clicked(self, obj):
|
||||
name = gen.lib.Name()
|
||||
try:
|
||||
@ -111,19 +150,48 @@ class NameEmbedList(EmbeddedList):
|
||||
pass
|
||||
|
||||
def add_callback(self, name):
|
||||
self.get_data().append(name)
|
||||
self.get_data()[self._WORKGROUP].append(name)
|
||||
self.rebuild()
|
||||
|
||||
def edit_button_clicked(self, obj):
|
||||
name = self.get_selected()
|
||||
if name:
|
||||
if name and name[1] is not None:
|
||||
try:
|
||||
from Editors import EditName
|
||||
|
||||
if name[0] == NameModel._ALTINDEX:
|
||||
EditName(self.dbstate, self.uistate, self.track,
|
||||
name, self.edit_callback)
|
||||
name[1], self.edit_callback)
|
||||
elif name[0] == NameModel._DEFINDEX:
|
||||
EditName(self.dbstate, self.uistate, self.track,
|
||||
name[1], self.editdef_callback)
|
||||
except Errors.WindowActiveError:
|
||||
pass
|
||||
|
||||
def edit_callback(self, name):
|
||||
self.rebuild()
|
||||
|
||||
def editdef_callback(self, name):
|
||||
"""
|
||||
callback after default name has changed
|
||||
"""
|
||||
self.rebuild()
|
||||
self.callback()
|
||||
|
||||
def dropnotworkgroup(self, row, obj):
|
||||
"""
|
||||
Drop of obj on row that is not WORKGROUP
|
||||
"""
|
||||
if row[0] == NameModel._DEFINDEX:
|
||||
#drop on default name
|
||||
self.set_default_name(obj)
|
||||
|
||||
def move_away_work(self, row_from, row_to, obj):
|
||||
"""
|
||||
move from the workgroup to a not workgroup
|
||||
we allow to change the default name like this
|
||||
"""
|
||||
if row_from[0] == self._WORKGROUP and row_to[0] == NameModel._DEFINDEX:
|
||||
self.set_default_name(obj)
|
||||
|
||||
def post_rebuild(self):
|
||||
self.tree.expand_all()
|
||||
|
@ -2,6 +2,7 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# 2009 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -20,12 +21,20 @@
|
||||
|
||||
# $Id$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# python libraries
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK libraries
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
from pango import WEIGHT_NORMAL, WEIGHT_BOLD
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -39,14 +48,90 @@ from BasicUtils import name_displayer
|
||||
# NameModel
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class NameModel(gtk.ListStore):
|
||||
|
||||
YES = _('Yes')
|
||||
NO = _('No')
|
||||
|
||||
class NameModel(gtk.TreeStore):
|
||||
#tree groups defined
|
||||
_DEFINDEX = 0
|
||||
_DEFNAME = _('Default Name')
|
||||
_ALTINDEX = 1
|
||||
_ALTNAME = _('Alternative Names')
|
||||
|
||||
_GROUPSTRING = _('%(groupname)s - %(groupnumber)d')
|
||||
|
||||
COL_NAME = (0, str)
|
||||
COL_TYPE = (1, str)
|
||||
COL_DATA = (2, object)
|
||||
COL_FONTWEIGHT = (3, int)
|
||||
COL_GROUPAS = (4, str)
|
||||
COL_HASSOURCE = (5, str)
|
||||
COL_NOTEPREVIEW = (6, str)
|
||||
|
||||
COLS = (COL_NAME, COL_TYPE, COL_DATA, COL_FONTWEIGHT, COL_GROUPAS,
|
||||
COL_HASSOURCE, COL_NOTEPREVIEW)
|
||||
|
||||
def __init__(self, obj_list, db):
|
||||
gtk.ListStore.__init__(self, str, str, object)
|
||||
typeobjs = (x[1] for x in self.COLS)
|
||||
gtk.TreeStore.__init__(self, *typeobjs)
|
||||
self.db = db
|
||||
for obj in obj_list:
|
||||
self.append(row=[
|
||||
name_displayer.display_name(obj),
|
||||
str(obj.get_type()),
|
||||
obj,
|
||||
])
|
||||
for index, group in enumerate(obj_list):
|
||||
|
||||
parentiter = self.append(None, row=self.row_group(index, group))
|
||||
for obj in group:
|
||||
self.append(parentiter, row = self.row(index, obj))
|
||||
|
||||
def row_group(self, index, group):
|
||||
name = self.namegroup(index, len(group))
|
||||
return [name, '', (index, None), WEIGHT_NORMAL, '', '', '']
|
||||
|
||||
def row(self, index, name):
|
||||
"""
|
||||
Returns the row of the model in group index, and name as a
|
||||
list
|
||||
"""
|
||||
return [name_displayer.display_name(name),
|
||||
str(name.get_type()),
|
||||
(index, name),
|
||||
self.colweight(index),
|
||||
name.get_group_as(),
|
||||
self.hassource(name),
|
||||
self.notepreview(name)
|
||||
]
|
||||
def colweight(self, index):
|
||||
if index == self._DEFINDEX:
|
||||
return WEIGHT_BOLD
|
||||
else:
|
||||
return WEIGHT_NORMAL
|
||||
|
||||
def namegroup(self, groupindex, length):
|
||||
if groupindex == self._DEFINDEX:
|
||||
return self._DEFNAME
|
||||
return self._GROUPSTRING % {'groupname': self._ALTNAME,
|
||||
'groupnumber': length}
|
||||
|
||||
def update_defname(self, defname):
|
||||
"""
|
||||
callback if change to the preferred name happens
|
||||
"""
|
||||
#default name is path (0,0)
|
||||
self.remove(self.get_iter((self._DEFINDEX, 0)))
|
||||
self.insert(self.get_iter(self._DEFINDEX), 0,
|
||||
row=self.row(self._DEFINDEX, defname))
|
||||
|
||||
def hassource(self, name):
|
||||
if len(name.get_source_references()):
|
||||
return YES
|
||||
return NO
|
||||
|
||||
def notepreview(self, name):
|
||||
nlist = name.get_note_list()
|
||||
if nlist:
|
||||
note = self.db.get_note_from_handle(nlist[0])
|
||||
text = unicode(note.get().replace('\n', ' '))
|
||||
if len(text) > 80:
|
||||
text = text[:80]+"..."
|
||||
return text
|
||||
else:
|
||||
return ''
|
||||
|
@ -68,9 +68,11 @@ class NoteTab(EmbeddedList):
|
||||
'down' : _('Move the selected note downwards'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Type'), 0, 100),
|
||||
(_('Preview'), 1, 200),
|
||||
(_('Type'), 0, 100, 0, -1),
|
||||
(_('Preview'), 1, 200, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data, callertitle=None,
|
||||
|
@ -56,10 +56,12 @@ class PersonRefEmbedList(EmbeddedList):
|
||||
'down' : _('Move the selected association downwards'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text
|
||||
_column_names = [
|
||||
(_('Name'), 0, 250),
|
||||
(_('ID'), 1, 100),
|
||||
(_('Association'), 2, 100),
|
||||
(_('Name'), 0, 250, 0, -1),
|
||||
(_('ID'), 1, 100, 0, -1),
|
||||
(_('Association'), 2, 100, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data):
|
||||
|
@ -58,11 +58,13 @@ class RepoEmbedList(EmbeddedList):
|
||||
'down' : _('Move the selected repository downwards'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('ID'), 0, 75),
|
||||
(_('Title'), 1, 200),
|
||||
(_('Call Number'), 2, 125),
|
||||
(_('Type'), 3, 100),
|
||||
(_('ID'), 0, 75, 0, -1),
|
||||
(_('Title'), 1, 200, 0, -1),
|
||||
(_('Call Number'), 2, 125, 0, -1),
|
||||
(_('Type'), 3, 100, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, obj):
|
||||
|
@ -58,11 +58,13 @@ class SourceEmbedList(EmbeddedList):
|
||||
'down' : _('Move the selected source downwards'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('ID'), 0, 75),
|
||||
(_('Title'), 1, 200),
|
||||
(_('Author'), 2, 125),
|
||||
(_('Page'), 3, 100),
|
||||
(_('ID'), 0, 75, 0, -1),
|
||||
(_('Title'), 1, 200, 0, -1),
|
||||
(_('Author'), 2, 125, 0, -1),
|
||||
(_('Page'), 3, 100, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, obj):
|
||||
|
@ -58,10 +58,12 @@ class WebEmbedList(EmbeddedList):
|
||||
'jump' : _('Jump to the selected web address'),
|
||||
}
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Type') , 0, 100),
|
||||
(_('Path') , 1, 200),
|
||||
(_('Description'), 2, 150),
|
||||
(_('Type') , 0, 100, 0, -1),
|
||||
(_('Path') , 1, 200, 0, -1),
|
||||
(_('Description'), 2, 150, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data):
|
||||
|
@ -288,7 +288,7 @@ class ChildEmbedList(EmbeddedList):
|
||||
pass
|
||||
break
|
||||
|
||||
def edit_child_button_clicked(self, obj):
|
||||
def edit_child_button_clicked(self):
|
||||
handle = self.get_selected()
|
||||
if handle:
|
||||
from Editors import EditPerson
|
||||
|
@ -2,6 +2,7 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# 2008-2009 Benny Malengier
|
||||
# 2009 Gary Burton
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
@ -304,7 +304,7 @@ class EditPerson(EditPrimary):
|
||||
self.top.get_object("call"),
|
||||
self.top.get_object("prefixentry"),
|
||||
]:
|
||||
obj.connect('changed', self._changed_title)
|
||||
obj.connect('changed', self._changed_name)
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
"""
|
||||
@ -399,18 +399,18 @@ class EditPerson(EditPrimary):
|
||||
self.top.get_object('vbox').pack_start(notebook, True)
|
||||
|
||||
|
||||
def _changed_title(self, obj):
|
||||
def _changed_name(self, obj):
|
||||
"""
|
||||
callback to changes typed by user to the person name.
|
||||
Update the window title
|
||||
Update the window title, and default name in name tab
|
||||
"""
|
||||
self.update_title(self.get_menu_title())
|
||||
self.name_list.update_defname()
|
||||
|
||||
def name_callback(self):
|
||||
"""
|
||||
Callback if changes happen in the name tab.
|
||||
The Preferred Name is _NOT_ part of the name tab, but name tab allows
|
||||
reorder and hence setting of new primary name.
|
||||
Callback if changes happen in the name tab that impact the preferred
|
||||
name.
|
||||
"""
|
||||
self.pname = self.obj.get_primary_name()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user