diff --git a/data/gramps.css b/data/gramps.css index f9b354424e4..8c947d4caa0 100644 --- a/data/gramps.css +++ b/data/gramps.css @@ -19,3 +19,7 @@ paned>separator { margin: 0px; padding: 1px; } + +label.error { + color: @error_color; +} diff --git a/gramps/gen/filters/rules/event/__init__.py b/gramps/gen/filters/rules/event/__init__.py index cba17446ecc..026db19f3c8 100644 --- a/gramps/gen/filters/rules/event/__init__.py +++ b/gramps/gen/filters/rules/event/__init__.py @@ -24,14 +24,13 @@ Package providing filter rules for Gramps. """ -from .._haseventbase import HasEventBase as HasEvent - from ._hastype import HasType from ._allevents import AllEvents from ._hasgallery import HasGallery from ._hasidof import HasIdOf from ._regexpidof import RegExpIdOf from ._hascitation import HasCitation +from ._hasevent import HasEvent from ._hasnote import HasNote from ._hasnoteregexp import HasNoteRegexp from ._hasnotematchingsubstringof import HasNoteMatchingSubstringOf diff --git a/gramps/gen/filters/rules/event/_hasevent.py b/gramps/gen/filters/rules/event/_hasevent.py new file mode 100644 index 00000000000..75210256869 --- /dev/null +++ b/gramps/gen/filters/rules/event/_hasevent.py @@ -0,0 +1,57 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2002-2006 Donald N. Allingham +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +Filter rule to match events with a particular value. +""" +# ------------------------------------------------------------------------- +# +# Standard Python modules +# +# ------------------------------------------------------------------------- +from ....const import GRAMPS_LOCALE as glocale + +_ = glocale.translation.gettext + +# ------------------------------------------------------------------------- +# +# Gramps modules +# +# ------------------------------------------------------------------------- +from .._haseventbase import HasEventBase + + +# ------------------------------------------------------------------------- +# +# HasEvent +# +# ------------------------------------------------------------------------- +class HasEvent(HasEventBase): + """Rule that checks for an event with a particular value""" + + labels = [ + _("Event type:"), + _("Date:"), + _("Place:"), + _("Description:"), + _("Main Participants:"), + ] + name = _("Events matching parameters") + description = _("Matches events with particular parameters") diff --git a/gramps/gen/filters/rules/source/__init__.py b/gramps/gen/filters/rules/source/__init__.py index 68c47caffa8..155f569c19c 100644 --- a/gramps/gen/filters/rules/source/__init__.py +++ b/gramps/gen/filters/rules/source/__init__.py @@ -24,8 +24,6 @@ Package providing filter rules for Gramps. """ -from .._hassourcebase import HasSourceBase as HasSource - from ._allsources import AllSources from ._hasattribute import HasAttribute from ._hasgallery import HasGallery @@ -36,6 +34,7 @@ from ._hasnotematchingsubstringof import HasNoteMatchingSubstringOf from ._hasnotetype import HasNoteType from ._hasreferencecountof import HasReferenceCountOf +from ._hassource import HasSource from ._sourceprivate import SourcePrivate from ._matchesfilter import MatchesFilter from ._changedsince import ChangedSince diff --git a/gramps/gen/filters/rules/source/_hassource.py b/gramps/gen/filters/rules/source/_hassource.py new file mode 100644 index 00000000000..3fb7ff531d1 --- /dev/null +++ b/gramps/gen/filters/rules/source/_hassource.py @@ -0,0 +1,51 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2002-2006 Donald N. Allingham +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +Filter rule to match sources with a particular value. +""" +# ------------------------------------------------------------------------- +# +# Standard Python modules +# +# ------------------------------------------------------------------------- +from ....const import GRAMPS_LOCALE as glocale + +_ = glocale.translation.gettext + +# ------------------------------------------------------------------------- +# +# Gramps modules +# +# ------------------------------------------------------------------------- +from .._hassourcebase import HasSourceBase + + +# ------------------------------------------------------------------------- +# +# HasSource +# +# ------------------------------------------------------------------------- +class HasSource(HasSourceBase): + """Rule that checks for a source with a particular value""" + + labels = [_("Title:"), _("Author:"), _("Abbreviation:"), _("Publication:")] + name = _("Sources matching parameters") + description = _("Matches sources with particular parameters") diff --git a/gramps/gui/filters/sidebar/_citationsidebarfilter.py b/gramps/gui/filters/sidebar/_citationsidebarfilter.py index 42478063210..bdadb93e807 100644 --- a/gramps/gui/filters/sidebar/_citationsidebarfilter.py +++ b/gramps/gui/filters/sidebar/_citationsidebarfilter.py @@ -78,7 +78,7 @@ def __init__(self, dbstate, uistate, clicked): for conf_value in sorted(conf_strings.keys()): model.append((_(conf_strings[conf_value]),)) self.filter_conf.set_model(model) - self.filter_conf.set_active(Citation.CONF_NORMAL) + self.filter_conf.set_active(Citation.CONF_VERY_LOW) self.filter_note = Gtk.Entry() diff --git a/gramps/gui/filters/sidebar/_personsidebarfilter.py b/gramps/gui/filters/sidebar/_personsidebarfilter.py index 053462be68c..fffacabe8a0 100644 --- a/gramps/gui/filters/sidebar/_personsidebarfilter.py +++ b/gramps/gui/filters/sidebar/_personsidebarfilter.py @@ -85,7 +85,9 @@ def __init__(self, dbstate, uistate, clicked): self.filter_name = widgets.BasicEntry() self.filter_id = widgets.BasicEntry() self.filter_birth = widgets.DateEntry(uistate, []) + self.filter_birth_place = widgets.BasicEntry() self.filter_death = widgets.DateEntry(uistate, []) + self.filter_death_place = widgets.BasicEntry() self.filter_event = Event() self.filter_event.set_type((EventType.CUSTOM, "")) self.etype = Gtk.ComboBox(has_entry=True) @@ -163,11 +165,13 @@ def create_widget(self): self.filter_birth, _('example: "%(msg1)s" or "%(msg2)s"') % {"msg1": msg1, "msg2": msg2}, ) + self.add_text_entry(_("Birth place"), self.filter_birth_place) self.add_text_entry( _("Death date"), self.filter_death, _('example: "%(msg1)s" or "%(msg2)s"') % {"msg1": msg1, "msg2": msg2}, ) + self.add_text_entry(_("Death place"), self.filter_death_place) self.add_entry(_("Event"), self.etype) self.add_text_entry(_("Note"), self.filter_note) self.add_entry(_("Tag"), self.tag) @@ -179,7 +183,9 @@ def clear(self, obj): self.filter_name.set_text("") self.filter_id.set_text("") self.filter_birth.set_text("") + self.filter_birth_place.set_text("") self.filter_death.set_text("") + self.filter_death_place.set_text("") self.filter_note.set_text("") self.filter_gender.set_active(0) self.etype.get_child().set_text("") @@ -196,7 +202,9 @@ def get_filter(self): name = extract_text(self.filter_name) gid = extract_text(self.filter_id) birth = extract_text(self.filter_birth) + birth_place = extract_text(self.filter_birth_place) death = extract_text(self.filter_death) + death_place = extract_text(self.filter_death_place) note = extract_text(self.filter_note) # extract remaining data from the menus @@ -214,7 +222,9 @@ def get_filter(self): name or gid or birth + or birth_place or death + or death_place or etype or note or gender @@ -271,13 +281,17 @@ def get_filter(self): # Arguments for the HasBirth filter are Date, Place, and Description # Since the value we extracted to the "birth" variable is the # request date, we pass it as the first argument - if birth: - rule = HasBirth([birth, "", ""]) + if birth or birth_place: + rule = HasBirth( + [birth, birth_place, ""], use_regex=regex, use_case=usecase + ) generic_filter.add_rule(rule) # Build death event filter if needed - if death: - rule = HasDeath([death, "", ""]) + if death or death_place: + rule = HasDeath( + [death, death_place, ""], use_regex=regex, use_case=usecase + ) generic_filter.add_rule(rule) # Build note filter if needed diff --git a/gramps/gui/filters/sidebar/_sidebarfilter.py b/gramps/gui/filters/sidebar/_sidebarfilter.py index ac1face8f41..54e638609bf 100644 --- a/gramps/gui/filters/sidebar/_sidebarfilter.py +++ b/gramps/gui/filters/sidebar/_sidebarfilter.py @@ -19,7 +19,21 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +# ------------------------------------------------------------------------- +# +# Python modules +# +# ------------------------------------------------------------------------- +import time + +# ------------------------------------------------------------------------- +# +# Gramps modules +# +# ------------------------------------------------------------------------- + from gramps.gen.const import GRAMPS_LOCALE as glocale +from gramps.gen.filters import reload_custom_filters _ = glocale.translation.gettext from bisect import insort_left @@ -32,6 +46,11 @@ from gramps.gen.config import config from ...utils import no_match_primary_mask +from ...editors import EditFilter +import gramps.gen.filters + +# import gramps.gen.filters.rules.place + _RETURN = Gdk.keyval_from_name("Return") _KP_ENTER = Gdk.keyval_from_name("KP_Enter") @@ -68,6 +87,17 @@ def __init__(self, dbstate, uistate, namespace): "defaults." ) ) + self.define_filter_btn = Gtk.Button(_("Define filter")) + self.define_filter_btn.set_tooltip_text( + _( + "This opens a dialog to add a new custom filter " + "based on the values given." + ) + ) + + self.msg_label = Gtk.Label() + self.msg_label.set_halign(Gtk.Align.START) + self.msg_label.set_margin_left(12) self._init_interface() uistate.connect("filters-changed", self.on_filters_changed) @@ -96,6 +126,7 @@ def _init_interface(self): self.clear_btn.add(hbox) self.clear_btn.connect("clicked", self.clear) + self.clear_btn.set_halign(Gtk.Align.END) hbox = Gtk.ButtonBox() hbox.set_layout(Gtk.ButtonBoxStyle.START) @@ -105,6 +136,17 @@ def _init_interface(self): hbox.add(self.clear_btn) hbox.show() self.vbox.pack_start(hbox, False, False, 0) + + self.define_filter_btn.connect("clicked", self.define_filter) + hbox = Gtk.ButtonBox() + hbox.set_layout(Gtk.ButtonBoxStyle.START) + hbox.set_spacing(6) + hbox.set_border_width(12) + hbox.add(self.define_filter_btn) + + self.vbox.pack_start(hbox, False, False, 0) + self.vbox.pack_start(self.msg_label, False, False, 0) + self.vbox.show() def get_widget(self): @@ -117,8 +159,15 @@ def clear(self, obj): pass def clicked(self, obj): + if not self.filter_is_ok(): + return self.uistate.set_busy_cursor(True) + t1 = time.perf_counter() self.clicked_func() + t2 = time.perf_counter() + msg = _("Elapsed time: %.2fs") % (t2 - t1) + self.msg_label.set_text(msg) + self.msg_label.get_style_context().remove_class("error") self.uistate.set_busy_cursor(False) def clicked_func(self): @@ -316,3 +365,57 @@ def set_filters_to_name(self, filter_name): self.generic.set_active_iter(iter) break iter = liststore.iter_next(iter) + + def filter_is_ok(self): + the_filter = self.get_filter() + if the_filter is None: + return True + for rule in the_filter.get_rules(): + if isinstance(rule, gramps.gen.filters.rules.place.WithinArea): + if rule.list[0] is None: # No active place + msg = _("You should select a place when using the 'Within' rule") + self.msg_label.set_text(msg) + self.msg_label.get_style_context().add_class("error") + return False + return True + + def define_filter(self, _obj): + self.filterdb = gramps.gen.filters.CustomFilters + the_filter = self.get_filter() + if the_filter is None: + self.msg_label.set_text(_("Supply at least one value")) + self.msg_label.get_style_context().add_class("error") + return + + if not self.filter_is_ok(): + return + # fix some rules: + new_rules = [] + for rule in the_filter.get_rules(): + # The Place rule WithinArea might have numeric values while custom_filters.xml only accepts strings. + if isinstance(rule, gramps.gen.filters.rules.place.WithinArea): + rule.list[1] = str(rule.list[1]) + rule.list[2] = str(rule.list[2]) + new_rules.append(rule) + the_filter.flist = new_rules + comment = _("Created by Filter gramplet on {today}").format( + today=time.strftime("%Y-%m-%d", time.localtime()) + ) + the_filter.set_comment(comment) + + self.msg_label.set_text("") + track = [] + EditFilter( + self.namespace, + self.dbstate, + self.uistate, + track, + the_filter, + self.filterdb, + update=self.update, + ) + + def update(self): + self.filterdb.save() + reload_custom_filters() + self.uistate.emit("filters-changed", (self.namespace,)) diff --git a/po/POTFILES.in b/po/POTFILES.in index 95716abeb5a..d8daec84c96 100755 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -76,6 +76,7 @@ gramps/gen/filters/rules/event/_hasattribute.py gramps/gen/filters/rules/event/_hascitation.py gramps/gen/filters/rules/event/_hasdata.py gramps/gen/filters/rules/event/_hasdayofweek.py +gramps/gen/filters/rules/event/_hasevent.py gramps/gen/filters/rules/event/_hasgallery.py gramps/gen/filters/rules/event/_hasidof.py gramps/gen/filters/rules/event/_hasnote.py @@ -288,6 +289,7 @@ gramps/gen/filters/rules/source/_hasnotetype.py gramps/gen/filters/rules/source/_hasreferencecountof.py gramps/gen/filters/rules/source/_hasrepository.py gramps/gen/filters/rules/source/_hasrepositorycallnumberref.py +gramps/gen/filters/rules/source/_hassource.py gramps/gen/filters/rules/source/_hastag.py gramps/gen/filters/rules/source/_matchesfilter.py gramps/gen/filters/rules/source/_matchesrepositoryfilter.py