* src/EventView.py (ui_definition): Add filter menu entry

* src/FamilyList.py (ui_definition): Add filter menu entry
* src/PlaceView.py (ui_definition): Add filter menu entry
* src/RepositoryView.py (ui_definition): Add filter menu entry
* src/SourceView.py (ui_definition): Add filter menu entry
* src/GenericFilter.py: Adding generic filter widget to be used in all list views; Custom filter rules now get prefixed by primary object type
* src/PageView.py: Add filter control to all list views
* src/PersonView.py: Filter handling moved to GenericFiler


svn: r5777
This commit is contained in:
Martin Hawlisch 2006-01-17 15:11:15 +00:00
parent 519f43c6c2
commit f0ea0adf9e
9 changed files with 232 additions and 209 deletions

View File

@ -1,3 +1,14 @@
2006-01-17 Martin Hawlisch <Martin.Hawlisch@gmx.de>
* src/EventView.py (ui_definition): Add filter menu entry
* src/FamilyList.py (ui_definition): Add filter menu entry
* src/PlaceView.py (ui_definition): Add filter menu entry
* src/RepositoryView.py (ui_definition): Add filter menu entry
* src/SourceView.py (ui_definition): Add filter menu entry
* src/GenericFilter.py: Adding generic filter widget to be used in all
list views; Custom filter rules now get prefixed by primary object type
* src/PageView.py: Add filter control to all list views
* src/PersonView.py: Filter handling moved to GenericFiler
2006-01-17 Richard Taylor <rjt-gramps@thegrindstone.me.uk>
* src/ObjectSelector/_FamilyFrame.py src/ObjectSelector/_FamilyPreviewFrame.py
src/ObjectSelector/_FamilyTreeFrame.py src/ObjectSelector/_ObjectSelectorWindow.py

View File

@ -86,6 +86,9 @@ class EventView(PageView.ListView):
def ui_definition(self):
return '''<ui>
<menubar name="MenuBar">
<menu action="ViewMenu">
<menuitem action="Filter"/>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>

View File

@ -90,6 +90,9 @@ class FamilyListView(PageView.ListView):
<menuitem action="Remove"/>
</placeholder>
</menu>
<menu action="ViewMenu">
<menuitem action="Filter"/>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonEdit">
@ -123,4 +126,3 @@ class FamilyListView(PageView.ListView):
import EditFamily
family = self.dbstate.db.get_family_from_handle(handle)
EditFamily.EditFamily(self.dbstate,self.uistate,[],family)

View File

@ -2279,14 +2279,19 @@ class GenericFilterList:
loads the filters."""
def __init__(self,file):
self.filter_list = []
self.filter_list = {}
self.file = os.path.expanduser(file)
def get_filters(self):
return self.filter_list
def get_filters(self,namespace):
try:
return self.filter_list[namespace]
except KeyError:
return []
def add(self,filt):
self.filter_list.append(filt)
def add(self,namespace,filt):
if namespace not in self.filter_list:
self.filter_list[namespace] = []
self.filter_list[namespace].append(filt)
def load(self):
try:
@ -2313,24 +2318,27 @@ class GenericFilterList:
f.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
f.write('<filters>\n')
for i in self.filter_list:
f.write(' <filter name="%s"' % self.fix(i.get_name()))
if i.get_invert():
f.write(' invert="1"')
f.write(' function="%s"' % i.get_logical_op())
comment = i.get_comment()
if comment:
f.write(' comment="%s"' % self.fix(comment))
f.write('>\n')
for rule in i.get_rules():
rule_module_name = rule.__module__
rule_class_name = rule.__class__.__name__
rule_save_name = "%s.%s" % (rule_module_name,rule_class_name)
f.write(' <rule class="%s">\n' % rule_save_name)
for v in rule.values():
f.write(' <arg value="%s"/>\n' % self.fix(v))
f.write(' </rule>\n')
f.write(' </filter>\n')
for namespace in self.filter_list:
f.write('<object "%s">\n' % "person")
for i in namespace:
f.write(' <filter name="%s"' % self.fix(i.get_name()))
if i.get_invert():
f.write(' invert="1"')
f.write(' function="%s"' % i.get_logical_op())
comment = i.get_comment()
if comment:
f.write(' comment="%s"' % self.fix(comment))
f.write('>\n')
for rule in i.get_rules():
rule_module_name = rule.__module__
rule_class_name = rule.__class__.__name__
rule_save_name = "%s.%s" % (rule_module_name,rule_class_name)
f.write(' <rule class="%s">\n' % rule_save_name)
for v in rule.values():
f.write(' <arg value="%s"/>\n' % self.fix(v))
f.write(' </rule>\n')
f.write(' </filter>\n')
f.write('</object>\n')
f.write('</filters>\n')
f.close()
@ -2349,12 +2357,18 @@ class FilterParser(handler.ContentHandler):
self.r = None
self.a = []
self.cname = None
self.namespace = "person"
def setDocumentLocator(self,locator):
self.locator = locator
def startElement(self,tag,attrs):
if tag == "filter":
if tag == "object":
if attrs.has_key('type'):
self.namespace = attrs['type']
else:
self.namespace = "generic"
elif tag == "filter":
self.f = GenericFilter()
self.f.set_name(attrs['name'])
if attrs.has_key('function'):
@ -2373,7 +2387,7 @@ class FilterParser(handler.ContentHandler):
self.f.set_invert(int(attrs['invert']))
except ValueError:
pass
self.gfilter_list.add(self.f)
self.gfilter_list.add(self.namespace,self.f)
elif tag == "rule":
save_name = attrs['class']
if save_name in old_names_2_class.keys():
@ -2529,7 +2543,7 @@ class GrampsFilterComboBox(gtk.ComboBox):
class FilterStore(gtk.ListStore):
def __init__(self,local_filters=[], default=""):
def __init__(self,local_filters=[], namespace="generic",default=""):
gtk.ListStore.__init__(self,str)
self.list_map = []
self.def_index = 0
@ -2543,7 +2557,7 @@ class FilterStore(gtk.ListStore):
self.def_index = cnt
cnt += 1
for filt in SystemFilters.get_filters() + CustomFilters.get_filters():
for filt in SystemFilters.get_filters(namespace) + CustomFilters.get_filters(namespace):
name = _(filt.get_name())
self.append(row=[name])
self.list_map.append(filt)
@ -2557,7 +2571,99 @@ class FilterStore(gtk.ListStore):
def get_filter(self,index):
return self.list_map[index]
class FilterWidget:
def __init__( self, uistate, on_apply, apply_done = None):
self.on_apply_callback = on_apply
self.apply_done_callback = apply_done
self.uistate = uistate
def build( self):
self.filterbar = gtk.HBox()
self.filterbar.set_spacing(4)
self.filter_text = gtk.Entry()
self.filter_label = gtk.Label('Label:')
self.filter_list = gtk.ComboBox()
self.filter_invert = gtk.CheckButton('Invert')
self.filter_button = gtk.Button('Apply')
self.filter_button.connect( 'clicked',self.apply_filter_clicked)
self.filterbar.pack_start(self.filter_list,False)
self.filterbar.pack_start(self.filter_label,False)
self.filterbar.pack_start(self.filter_text,True)
self.filterbar.pack_start(self.filter_invert,False)
self.filterbar.pack_end(self.filter_button,False)
self.filter_text.set_sensitive(False)
return self.filterbar
def setup_filter( self, default_filters, namespace="generic"):
cell = gtk.CellRendererText()
self.filter_list.clear()
self.filter_list.pack_start(cell,True)
self.filter_list.add_attribute(cell,'text',0)
filter_list = []
for f in default_filters:
all = GenericFilter()
rule = f[0](f[1])
print rule
all.set_name( rule.name)
all.add_rule( rule)
filter_list.append(all)
self.filter_model = FilterStore(filter_list, namespace)
self.filter_list.set_model(self.filter_model)
self.filter_list.set_active(self.filter_model.default_index())
self.filter_list.connect('changed',self.on_filter_name_changed)
self.filter_text.set_sensitive(False)
self.DataFilter = filter_list[self.filter_model.default_index()]
def apply_filter_clicked(self,ev=None):
print "apply_filter_clicked"
index = self.filter_list.get_active()
self.DataFilter = self.filter_model.get_filter(index)
if self.DataFilter.need_param:
qual = unicode(self.filter_text.get_text())
self.DataFilter.set_parameter(qual)
self.apply_filter()
if self.apply_done_callback:
self.apply_done_callback()
def on_filter_name_changed(self,obj):
print "on_filter_name_changed"
index = self.filter_list.get_active()
mime_filter = self.filter_model.get_filter(index)
qual = mime_filter.need_param
if qual:
self.filter_text.show()
self.filter_text.set_sensitive(True)
self.filter_label.show()
self.filter_label.set_text(mime_filter.get_rules()[0].labels[0])
else:
self.filter_text.hide()
self.filter_text.set_sensitive(False)
self.filter_label.hide()
def apply_filter(self,current_model=None):
self.uistate.status_text(_('Updating display...'))
self.on_apply_callback()
self.uistate.modify_statusbar()
def get_filter( self):
print "get_filter"
print self.DataFilter.flist[0]
return self.DataFilter
def inverted( self):
return self.filter_invert.get_active()
def show( self):
self.filterbar.show()
def hide( self):
self.filterbar.hide()
def build_filter_menu(local_filters = [], default=""):
menu = gtk.Menu()

View File

@ -22,6 +22,7 @@
import gtk
import TreeTips
import GenericFilter
NAVIGATION_NONE = -1
NAVIGATION_PERSON = 0
@ -316,6 +317,13 @@ class ListView(PageView):
contains the interface. This containter will be inserted into
a gtk.Notebook page.
"""
self.vbox = gtk.VBox()
self.vbox.set_border_width(0)
self.vbox.set_spacing(4)
self.generic_filter_widget = GenericFilter.FilterWidget( self.uistate, self.build_tree)
filter_box = self.generic_filter_widget.build()
self.list = gtk.TreeView()
self.list.set_rules_hint(True)
self.list.set_headers_visible(True)
@ -328,6 +336,9 @@ class ListView(PageView):
scrollwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN)
scrollwindow.add(self.list)
self.vbox.pack_start(filter_box,False)
self.vbox.pack_start(scrollwindow,True)
self.renderer = gtk.CellRendererText()
self.inactive = False
@ -336,8 +347,22 @@ class ListView(PageView):
self.selection = self.list.get_selection()
#self.selection.connect('changed',self.row_changed)
return scrollwindow
self.setup_filter()
return self.vbox
def setup_filter(self):
"""
Builds the default filters and add them to the filter menu.
"""
default_filters = [
[GenericFilter.Everyone, []],
[GenericFilter.HasTextMatchingSubstringOf, ['',0,0]],
[GenericFilter.HasTextMatchingRegexpOf, ['',0,1]],
[GenericFilter.PeoplePrivate, []],
]
self.generic_filter_widget.setup_filter( default_filters)
def column_clicked(self,obj,data):
if self.sort_col != data:
order = gtk.SORT_ASCENDING
@ -419,6 +444,8 @@ class ListView(PageView):
self.add_action('Add', gtk.STOCK_ADD, "_Add", callback=self.add)
self.add_action('Edit', gtk.STOCK_EDIT, "_Edit", callback=self.edit)
self.add_action('Remove',gtk.STOCK_REMOVE,"_Remove",callback=self.remove)
self.add_toggle_action('Filter', None, '_Filter',
callback=self.filter_toggle)
def button_press(self,obj,event):
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
@ -440,3 +467,9 @@ class ListView(PageView):
def double_click(self,obj,event):
return False
def filter_toggle(self,obj):
if obj.get_active():
self.generic_filter_widget.show()
else:
self.generic_filter_widget.hide()

View File

@ -78,7 +78,7 @@ class PersonView(PageView.PersonNavView):
self.handle_col = len(column_names)+2
def change_page(self):
self.on_filter_name_changed(None)
self.generic_filter_widget.on_filter_name_changed(None)
def define_actions(self):
"""
@ -126,20 +126,9 @@ class PersonView(PageView.PersonNavView):
self.vbox.set_border_width(4)
self.vbox.set_spacing(4)
self.filterbar = gtk.HBox()
self.filterbar.set_spacing(4)
self.filter_text = gtk.Entry()
self.filter_label = gtk.Label('Label:')
self.filter_list = gtk.ComboBox()
self.filter_invert = gtk.CheckButton('Invert')
self.filter_button = gtk.Button('Apply')
self.filterbar.pack_start(self.filter_list,False)
self.filterbar.pack_start(self.filter_label,False)
self.filterbar.pack_start(self.filter_text,True)
self.filterbar.pack_start(self.filter_invert,False)
self.filterbar.pack_end(self.filter_button,False)
self.filter_text.set_sensitive(False)
self.generic_filter_widget = GenericFilter.FilterWidget( self.uistate, self.build_tree, self.goto_active_person)
filter_box = self.generic_filter_widget.build()
self.tree = gtk.TreeView()
self.tree.set_rules_hint(True)
@ -152,7 +141,7 @@ class PersonView(PageView.PersonNavView):
scrollwindow.add(self.tree)
scrollwindow.show_all()
self.vbox.pack_start(self.filterbar,False)
self.vbox.pack_start(filter_box,False)
self.vbox.pack_start(scrollwindow,True)
self.renderer = gtk.CellRendererText()
@ -168,9 +157,9 @@ class PersonView(PageView.PersonNavView):
self.selection.set_mode(gtk.SELECTION_MULTIPLE)
self.selection.connect('changed',self.row_changed)
self.vbox.set_focus_chain([self.tree, self.filter_list,
self.filter_text, self.filter_invert,
self.filter_button])
#self.vbox.set_focus_chain([self.tree, self.filter_list,
# self.filter_text, self.filter_invert,
# self.filter_button])
self.setup_filter()
return self.vbox
@ -239,7 +228,7 @@ class PersonView(PageView.PersonNavView):
db.connect('person-update', self.person_updated)
db.connect('person-delete', self.person_removed)
db.connect('person-rebuild', self.build_tree)
self.apply_filter()
self.generic_filter_widget.apply_filter()
def goto_active_person(self,obj=None):
"""
@ -298,135 +287,32 @@ class PersonView(PageView.PersonNavView):
"""
Builds the default filters and add them to the filter menu.
"""
cell = gtk.CellRendererText()
self.filter_list.clear()
self.filter_list.pack_start(cell,True)
self.filter_list.add_attribute(cell,'text',0)
filter_list = []
self.DataFilter = None
all = GenericFilter.GenericFilter()
all.set_name(_("Entire Database"))
all.add_rule(GenericFilter.Everyone([]))
all = GenericFilter.GenericFilter()
all.set_name(_("Entire Database"))
all.add_rule(GenericFilter.Everyone([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("Females"))
all.add_rule(GenericFilter.IsFemale([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("Males"))
all.add_rule(GenericFilter.IsMale([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("People with unknown gender"))
all.add_rule(GenericFilter.HasUnknownGender([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("Disconnected individuals"))
all.add_rule(GenericFilter.Disconnected([]))
filter_list.append(all)
all = GenericFilter.ParamFilter()
all.set_name(_("People with names containing..."))
all.add_rule(GenericFilter.SearchName(['']))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("Adopted people"))
all.add_rule(GenericFilter.HaveAltFamilies([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("People with images"))
all.add_rule(GenericFilter.HavePhotos([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("People with incomplete names"))
all.add_rule(GenericFilter.IncompleteNames([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("People with children"))
all.add_rule(GenericFilter.HaveChildren([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("People with no marriage records"))
all.add_rule(GenericFilter.NeverMarried([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("People with multiple marriage records"))
all.add_rule(GenericFilter.MultipleMarriages([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("People without a known birth date"))
all.add_rule(GenericFilter.NoBirthdate([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("People with incomplete events"))
all.add_rule(GenericFilter.PersonWithIncompleteEvent([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("Families with incomplete events"))
all.add_rule(GenericFilter.FamilyWithIncompleteEvent([]))
filter_list.append(all)
all = GenericFilter.ParamFilter()
all.set_name(_("People probably alive"))
all.add_rule(GenericFilter.ProbablyAlive(['']))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("People marked private"))
all.add_rule(GenericFilter.PeoplePrivate([]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("Witnesses"))
all.add_rule(GenericFilter.IsWitness(['','']))
filter_list.append(all)
all = GenericFilter.ParamFilter()
all.set_name(_("People with records containing..."))
all.add_rule(GenericFilter.HasTextMatchingSubstringOf(['',0,0]))
filter_list.append(all)
all = GenericFilter.ParamFilter()
all.set_name(_("People with records matching regular expression..."))
all.add_rule(GenericFilter.HasTextMatchingRegexpOf(['',0,1]))
filter_list.append(all)
all = GenericFilter.GenericFilter()
all.set_name(_("People with notes"))
all.add_rule(GenericFilter.HasNote([]))
filter_list.append(all)
all = GenericFilter.ParamFilter()
all.set_name(_("People with notes containing..."))
all.add_rule(GenericFilter.HasNoteMatchingSubstringOf(['']))
filter_list.append(all)
self.filter_model = GenericFilter.FilterStore(filter_list)
self.filter_list.set_model(self.filter_model)
self.filter_list.set_active(self.filter_model.default_index())
self.filter_list.connect('changed',self.on_filter_name_changed)
self.filter_text.set_sensitive(False)
default_filters = [
[GenericFilter.Everyone, []],
[GenericFilter.IsFemale, []],
[GenericFilter.IsMale, []],
[GenericFilter.HasUnknownGender, []],
[GenericFilter.Disconnected, []],
[GenericFilter.SearchName, ['']],
[GenericFilter.HaveAltFamilies, []],
[GenericFilter.HavePhotos, []],
[GenericFilter.IncompleteNames, []],
[GenericFilter.HaveChildren, []],
[GenericFilter.NeverMarried, []],
[GenericFilter.MultipleMarriages, []],
[GenericFilter.NoBirthdate, []],
[GenericFilter.PersonWithIncompleteEvent, []],
[GenericFilter.FamilyWithIncompleteEvent, []],
[GenericFilter.ProbablyAlive, ['']],
[GenericFilter.PeoplePrivate, []],
[GenericFilter.IsWitness, ['','']],
[GenericFilter.HasTextMatchingSubstringOf, ['',0,0]],
[GenericFilter.HasTextMatchingRegexpOf, ['',0,1]],
[GenericFilter.HasNote, []],
[GenericFilter.HasNoteMatchingSubstringOf, ['']],
[GenericFilter.IsFemale, []],
]
self.generic_filter_widget.setup_filter( default_filters, "person")
def build_tree(self):
"""
@ -434,7 +320,7 @@ class PersonView(PageView.PersonNavView):
rebuild of the data.
"""
self.model = PeopleModel.PeopleModel(
self.dbstate.db, self.DataFilter, self.filter_invert.get_active())
self.dbstate.db, self.generic_filter_widget.get_filter(), self.generic_filter_widget.inverted())
self.tree.set_model(self.model)
if self.model.tooltip_column != None:
@ -444,9 +330,9 @@ class PersonView(PageView.PersonNavView):
def filter_toggle(self,obj):
if obj.get_active():
self.filterbar.show()
self.generic_filter_widget.show()
else:
self.filterbar.hide()
self.generic_filter_widget.hide()
def add(self,obj):
person = RelLib.Person()
@ -592,15 +478,6 @@ class PersonView(PageView.PersonNavView):
sel_data.set(DdTargets.PERSON_LINK_LIST.drag_type,8,
pickle.dumps(selected_ids))
def apply_filter_clicked(self):
index = self.filter_list.get_active()
self.DataFilter = self.filter_model.get_filter(index)
if self.DataFilter.need_param:
qual = unicode(self.filter_text.get_text())
self.DataFilter.set_parameter(qual)
self.apply_filter()
self.goto_active_person()
def person_added(self,handle_list):
for node in handle_list:
person = self.dbstate.db.get_person_from_handle(node)
@ -697,24 +574,6 @@ class PersonView(PageView.PersonNavView):
self.goto_active_person()
def on_filter_name_changed(self,obj):
index = self.filter_list.get_active()
mime_filter = self.filter_model.get_filter(index)
qual = mime_filter.need_param
if qual:
self.filter_text.show()
self.filter_text.set_sensitive(True)
self.filter_label.show()
self.filter_label.set_text(mime_filter.get_rules()[0].labels[0])
else:
self.filter_text.hide()
self.filter_text.set_sensitive(False)
self.filter_label.hide()
def apply_filter(self,current_model=None):
self.uistate.status_text(_('Updating display...'))
self.build_tree()
self.uistate.modify_statusbar()
def get_selected_objects(self):
(mode,paths) = self.selection.get_selected_rows()

View File

@ -90,6 +90,9 @@ class PlaceView(PageView.ListView):
def ui_definition(self):
return '''<ui>
<menubar name="MenuBar">
<menu action="ViewMenu">
<menuitem action="Filter"/>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>

View File

@ -93,6 +93,9 @@ class RepositoryView(PageView.ListView):
def ui_definition(self):
return '''<ui>
<menubar name="MenuBar">
<menu action="ViewMenu">
<menuitem action="Filter"/>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>

View File

@ -85,6 +85,9 @@ class SourceView(PageView.ListView):
def ui_definition(self):
return '''<ui>
<menubar name="MenuBar">
<menu action="ViewMenu">
<menuitem action="Filter"/>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>