From 46ded3e7dbbc90cdc269319da81b5dc5e40623b7 Mon Sep 17 00:00:00 2001 From: Nick Hall Date: Tue, 22 Jan 2013 16:12:15 +0000 Subject: [PATCH] Add tagging to all primary objects svn: r21194 --- data/grampsxml.dtd | 19 +- data/grampsxml.rng | 17 +- gramps/gen/db/upgrade.py | 89 ++++++ gramps/gen/db/write.py | 4 +- gramps/gen/filters/rules/citation/__init__.py | 4 +- gramps/gen/filters/rules/citation/_hastag.py | 51 +++ gramps/gen/filters/rules/event/__init__.py | 4 +- gramps/gen/filters/rules/event/_hastag.py | 51 +++ gramps/gen/filters/rules/place/__init__.py | 2 + gramps/gen/filters/rules/place/_hastag.py | 51 +++ .../gen/filters/rules/repository/__init__.py | 4 +- .../gen/filters/rules/repository/_hastag.py | 51 +++ gramps/gen/filters/rules/source/__init__.py | 4 +- gramps/gen/filters/rules/source/_hastag.py | 51 +++ gramps/gen/lib/citation.py | 15 +- gramps/gen/lib/event.py | 13 +- gramps/gen/lib/family.py | 3 +- gramps/gen/lib/mediaobj.py | 3 +- gramps/gen/lib/note.py | 3 +- gramps/gen/lib/person.py | 3 +- gramps/gen/lib/place.py | 13 +- gramps/gen/lib/primaryobj.py | 4 +- gramps/gen/lib/repo.py | 11 +- gramps/gen/lib/src.py | 11 +- gramps/gui/editors/editcitation.py | 22 +- gramps/gui/editors/editevent.py | 18 +- gramps/gui/editors/editplace.py | 10 +- gramps/gui/editors/editrepository.py | 14 +- gramps/gui/editors/editsource.py | 12 +- .../filters/sidebar/_citationsidebarfilter.py | 45 ++- .../filters/sidebar/_eventsidebarfilter.py | 45 ++- .../filters/sidebar/_placesidebarfilter.py | 34 +- .../gui/filters/sidebar/_reposidebarfilter.py | 45 ++- .../filters/sidebar/_sourcesidebarfilter.py | 47 ++- gramps/gui/glade/editcitation.glade | 291 ++++++++++++------ gramps/gui/glade/editevent.glade | 206 ++++++++----- gramps/gui/glade/editplace.glade | 168 ++++++---- gramps/gui/glade/editrepository.glade | 65 +++- gramps/gui/glade/editsource.glade | 185 ++++++----- gramps/gui/views/listview.py | 14 +- gramps/gui/views/tags.py | 4 +- .../gui/views/treemodels/citationbasemodel.py | 66 +++- .../gui/views/treemodels/citationlistmodel.py | 10 + .../gui/views/treemodels/citationtreemodel.py | 14 + gramps/gui/views/treemodels/eventmodel.py | 42 ++- gramps/gui/views/treemodels/placemodel.py | 41 ++- gramps/gui/views/treemodels/repomodel.py | 41 ++- gramps/gui/views/treemodels/sourcemodel.py | 41 ++- gramps/plugins/export/exportxml.py | 20 ++ gramps/plugins/importer/importxml.py | 17 +- gramps/plugins/lib/libgrampsxml.py | 2 +- gramps/plugins/lib/libpersonview.py | 15 - gramps/plugins/lib/libplaceview.py | 29 +- gramps/plugins/view/citationlistview.py | 48 ++- gramps/plugins/view/citationtreeview.py | 34 +- gramps/plugins/view/eventview.py | 30 +- gramps/plugins/view/familyview.py | 15 - gramps/plugins/view/mediaview.py | 15 - gramps/plugins/view/noteview.py | 15 - gramps/plugins/view/placetreeview.py | 12 +- gramps/plugins/view/repoview.py | 29 +- gramps/plugins/view/sourceview.py | 28 +- 62 files changed, 1731 insertions(+), 539 deletions(-) create mode 100644 gramps/gen/filters/rules/citation/_hastag.py create mode 100644 gramps/gen/filters/rules/event/_hastag.py create mode 100644 gramps/gen/filters/rules/place/_hastag.py create mode 100644 gramps/gen/filters/rules/repository/_hastag.py create mode 100644 gramps/gen/filters/rules/source/_hastag.py diff --git a/data/grampsxml.dtd b/data/grampsxml.dtd index 667c4a317..0c7f2958b 100644 --- a/data/grampsxml.dtd +++ b/data/grampsxml.dtd @@ -25,15 +25,15 @@ --> @@ -215,7 +215,8 @@ EVENT + description?, attribute*, noteref*, citationref*, objref*, + tagref*)> + noteref*, objref*, data_item*, reporef*, tagref*)> + citationref*, tagref*)> - + + noteref*, objref*, data_item*, sourceref, tagref*)> @@ -160,6 +160,9 @@ 0 1 + + + @@ -205,9 +208,6 @@ - - - @@ -403,9 +403,6 @@ - - - @@ -520,9 +517,6 @@ - - - @@ -581,9 +575,6 @@ - - - diff --git a/gramps/gen/db/upgrade.py b/gramps/gen/db/upgrade.py index 1df9bf040..ef0b1eb8a 100644 --- a/gramps/gen/db/upgrade.py +++ b/gramps/gen/db/upgrade.py @@ -43,12 +43,101 @@ if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3: else: from bsddb import db from . import BSDDBTxn +from ..constfunc import UNITYPE from ..lib.nameorigintype import NameOriginType from .write import _mkname, SURNAMES from .dbconst import (PERSON_KEY, FAMILY_KEY, EVENT_KEY, MEDIA_KEY, PLACE_KEY, REPOSITORY_KEY) from gramps.gui.dialog import (InfoDialog) +def gramps_upgrade_17(self): + """Upgrade database from version 16 to 17. This upgrade adds tags to + event, place, repository, source and citation objects. + """ + length = (len(self.event_map) + len(self.place_map) + + len(self.repository_map) + len(self.source_map) + + len(self.citation_map)) + self.set_total(length) + + # --------------------------------- + # Modify Event + # --------------------------------- + # Add new tag_list field. + for handle in self.event_map.keys(): + event = self.event_map[handle] + new_event = list(event) + new_event = new_event[:11] + [[]] + new_event[11:] + new_event = tuple(new_event) + with BSDDBTxn(self.env, self.event_map) as txn: + if isinstance(handle, UNITYPE): + handle = handle.encode('utf-8') + txn.put(handle, new_event) + self.update() + + # --------------------------------- + # Modify Place + # --------------------------------- + # Add new tag_list field. + for handle in self.place_map.keys(): + place = self.place_map[handle] + new_place = list(place) + new_place = new_place[:12] + [[]] + new_place[12:] + new_place = tuple(new_place) + with BSDDBTxn(self.env, self.place_map) as txn: + if isinstance(handle, UNITYPE): + handle = handle.encode('utf-8') + txn.put(handle, new_place) + self.update() + + # --------------------------------- + # Modify Repository + # --------------------------------- + # Add new tag_list field. + for handle in self.repository_map.keys(): + repository = self.repository_map[handle] + new_repository = list(repository) + new_repository = new_repository[:8] + [[]] + new_repository[8:] + new_repository = tuple(new_repository) + with BSDDBTxn(self.env, self.repository_map) as txn: + if isinstance(handle, UNITYPE): + handle = handle.encode('utf-8') + txn.put(handle, new_repository) + self.update() + + # --------------------------------- + # Modify Source + # --------------------------------- + # Add new tag_list field. + for handle in self.source_map.keys(): + source = self.source_map[handle] + new_source = list(source) + new_source = new_source[:11] + [[]] + new_source[11:] + new_source = tuple(new_source) + with BSDDBTxn(self.env, self.source_map) as txn: + if isinstance(handle, UNITYPE): + handle = handle.encode('utf-8') + txn.put(handle, new_source) + self.update() + + # --------------------------------- + # Modify Citation + # --------------------------------- + # Add new tag_list field. + for handle in self.citation_map.keys(): + citation = self.citation_map[handle] + new_citation = list(citation) + new_citation = new_citation[:10] + [[]] + new_citation[10:] + new_citation = tuple(new_citation) + with BSDDBTxn(self.env, self.citation_map) as txn: + if isinstance(handle, UNITYPE): + handle = handle.encode('utf-8') + txn.put(handle, new_citation) + self.update() + + # Bump up database version. Separate transaction to save metadata. + with BSDDBTxn(self.env, self.metadata) as txn: + txn.put(b'version', 17) + def gramps_upgrade_16(self): """Upgrade database from version 15 to 16. This upgrade converts all SourceRef child objects to Citation Primary objects. diff --git a/gramps/gen/db/write.py b/gramps/gen/db/write.py index 417bb557c..aadd976fe 100644 --- a/gramps/gen/db/write.py +++ b/gramps/gen/db/write.py @@ -86,7 +86,7 @@ from ..constfunc import win, conv_to_unicode, cuni, UNITYPE, handle2internal _LOG = logging.getLogger(DBLOGNAME) LOG = logging.getLogger(".citation") _MINVERSION = 9 -_DBVERSION = 16 +_DBVERSION = 17 IDTRANS = "person_id" FIDTRANS = "family_id" @@ -2005,6 +2005,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): upgrade.gramps_upgrade_15(self) if version < 16: upgrade.gramps_upgrade_16(self) + if version < 17: + upgrade.gramps_upgrade_17(self) self.reset() self.set_total(6) diff --git a/gramps/gen/filters/rules/citation/__init__.py b/gramps/gen/filters/rules/citation/__init__.py index 717879e8e..d29446045 100644 --- a/gramps/gen/filters/rules/citation/__init__.py +++ b/gramps/gen/filters/rules/citation/__init__.py @@ -42,6 +42,7 @@ from ._matchespagesubstringof import MatchesPageSubstringOf from ._matchesrepositoryfilter import MatchesRepositoryFilter from ._matchessourcefilter import MatchesSourceFilter from ._regexpidof import RegExpIdOf +from ._hastag import HasTag editor_rule_list = [ HasCitation, @@ -59,5 +60,6 @@ editor_rule_list = [ MatchesPageSubstringOf, MatchesRepositoryFilter, MatchesSourceFilter, - RegExpIdOf + RegExpIdOf, + HasTag ] diff --git a/gramps/gen/filters/rules/citation/_hastag.py b/gramps/gen/filters/rules/citation/_hastag.py new file mode 100644 index 000000000..a5c1ddf22 --- /dev/null +++ b/gramps/gen/filters/rules/citation/_hastag.py @@ -0,0 +1,51 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2010 Nick Hall +# +# 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$ +""" +Rule that checks for a citation with a particular tag. +""" + +#------------------------------------------------------------------------- +# +# Standard Python modules +# +#------------------------------------------------------------------------- +from ....const import GRAMPS_LOCALE as glocale +_ = glocale.get_translation().gettext + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +from .._hastagbase import HasTagBase + +#------------------------------------------------------------------------- +# +# HasTag +# +#------------------------------------------------------------------------- +class HasTag(HasTagBase): + """ + Rule that checks for a citation with a particular tag. + """ + labels = [ _('Tag:') ] + name = _('Citations with the ') + description = _("Matches citations with the particular tag") diff --git a/gramps/gen/filters/rules/event/__init__.py b/gramps/gen/filters/rules/event/__init__.py index 41c3132d0..16100b4cc 100644 --- a/gramps/gen/filters/rules/event/__init__.py +++ b/gramps/gen/filters/rules/event/__init__.py @@ -47,6 +47,7 @@ from ._matchessourcefilter import MatchesSourceFilter from ._hasattribute import HasAttribute from ._hasdata import HasData from ._changedsince import ChangedSince +from ._hastag import HasTag editor_rule_list = [ AllEvents, @@ -67,5 +68,6 @@ editor_rule_list = [ MatchesSourceFilter, HasAttribute, HasData, - ChangedSince + ChangedSince, + HasTag ] diff --git a/gramps/gen/filters/rules/event/_hastag.py b/gramps/gen/filters/rules/event/_hastag.py new file mode 100644 index 000000000..ebcf9fe8f --- /dev/null +++ b/gramps/gen/filters/rules/event/_hastag.py @@ -0,0 +1,51 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2010 Nick Hall +# +# 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$ +""" +Rule that checks for an event with a particular tag. +""" + +#------------------------------------------------------------------------- +# +# Standard Python modules +# +#------------------------------------------------------------------------- +from ....const import GRAMPS_LOCALE as glocale +_ = glocale.get_translation().gettext + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +from .._hastagbase import HasTagBase + +#------------------------------------------------------------------------- +# +# HasTag +# +#------------------------------------------------------------------------- +class HasTag(HasTagBase): + """ + Rule that checks for an event with a particular tag. + """ + labels = [ _('Tag:') ] + name = _('Events with the ') + description = _("Matches events with the particular tag") diff --git a/gramps/gen/filters/rules/place/__init__.py b/gramps/gen/filters/rules/place/__init__.py index b893d1b20..57d8071cc 100644 --- a/gramps/gen/filters/rules/place/__init__.py +++ b/gramps/gen/filters/rules/place/__init__.py @@ -44,6 +44,7 @@ from ._inlatlonneighborhood import InLatLonNeighborhood from ._matcheseventfilter import MatchesEventFilter from ._matchessourceconfidence import MatchesSourceConfidence from ._changedsince import ChangedSince +from ._hastag import HasTag editor_rule_list = [ AllPlaces, @@ -65,4 +66,5 @@ editor_rule_list = [ InLatLonNeighborhood, MatchesEventFilter, ChangedSince, + HasTag ] diff --git a/gramps/gen/filters/rules/place/_hastag.py b/gramps/gen/filters/rules/place/_hastag.py new file mode 100644 index 000000000..7f70998c6 --- /dev/null +++ b/gramps/gen/filters/rules/place/_hastag.py @@ -0,0 +1,51 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2010 Nick Hall +# +# 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$ +""" +Rule that checks for a place with a particular tag. +""" + +#------------------------------------------------------------------------- +# +# Standard Python modules +# +#------------------------------------------------------------------------- +from ....const import GRAMPS_LOCALE as glocale +_ = glocale.get_translation().gettext + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +from .._hastagbase import HasTagBase + +#------------------------------------------------------------------------- +# +# HasTag +# +#------------------------------------------------------------------------- +class HasTag(HasTagBase): + """ + Rule that checks for a place with a particular tag. + """ + labels = [ _('Tag:') ] + name = _('Places with the ') + description = _("Matches places with the particular tag") diff --git a/gramps/gen/filters/rules/repository/__init__.py b/gramps/gen/filters/rules/repository/__init__.py index 13761fef3..b3c32f9eb 100644 --- a/gramps/gen/filters/rules/repository/__init__.py +++ b/gramps/gen/filters/rules/repository/__init__.py @@ -35,6 +35,7 @@ from ._matchesfilter import MatchesFilter from ._hasrepo import HasRepo from ._changedsince import ChangedSince from ._matchesnamesubstringof import MatchesNameSubstringOf +from ._hastag import HasTag editor_rule_list = [ AllRepos, @@ -46,5 +47,6 @@ editor_rule_list = [ RepoPrivate, MatchesFilter, ChangedSince, - MatchesNameSubstringOf + MatchesNameSubstringOf, + HasTag ] diff --git a/gramps/gen/filters/rules/repository/_hastag.py b/gramps/gen/filters/rules/repository/_hastag.py new file mode 100644 index 000000000..5011ef881 --- /dev/null +++ b/gramps/gen/filters/rules/repository/_hastag.py @@ -0,0 +1,51 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2010 Nick Hall +# +# 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$ +""" +Rule that checks for a repository with a particular tag. +""" + +#------------------------------------------------------------------------- +# +# Standard Python modules +# +#------------------------------------------------------------------------- +from ....const import GRAMPS_LOCALE as glocale +_ = glocale.get_translation().gettext + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +from .._hastagbase import HasTagBase + +#------------------------------------------------------------------------- +# +# HasTag +# +#------------------------------------------------------------------------- +class HasTag(HasTagBase): + """ + Rule that checks for a repository with a particular tag. + """ + labels = [ _('Tag:') ] + name = _('Repositories with the ') + description = _("Matches repositories with the particular tag") diff --git a/gramps/gen/filters/rules/source/__init__.py b/gramps/gen/filters/rules/source/__init__.py index fd67b8a40..696d8f5f7 100644 --- a/gramps/gen/filters/rules/source/__init__.py +++ b/gramps/gen/filters/rules/source/__init__.py @@ -43,6 +43,7 @@ from ._hasrepository import HasRepository from ._matchestitlesubstringof import MatchesTitleSubstringOf from ._hasrepositorycallnumberref import HasRepositoryCallNumberRef from ._matchesrepositoryfilter import MatchesRepositoryFilter +from ._hastag import HasTag editor_rule_list = [ AllSources, @@ -59,5 +60,6 @@ editor_rule_list = [ HasRepository, MatchesTitleSubstringOf, HasRepositoryCallNumberRef, - MatchesRepositoryFilter + MatchesRepositoryFilter, + HasTag ] diff --git a/gramps/gen/filters/rules/source/_hastag.py b/gramps/gen/filters/rules/source/_hastag.py new file mode 100644 index 000000000..7a1480fce --- /dev/null +++ b/gramps/gen/filters/rules/source/_hastag.py @@ -0,0 +1,51 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2010 Nick Hall +# +# 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$ +""" +Rule that checks for a source with a particular tag. +""" + +#------------------------------------------------------------------------- +# +# Standard Python modules +# +#------------------------------------------------------------------------- +from ....const import GRAMPS_LOCALE as glocale +_ = glocale.get_translation().gettext + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +from .._hastagbase import HasTagBase + +#------------------------------------------------------------------------- +# +# HasTag +# +#------------------------------------------------------------------------- +class HasTag(HasTagBase): + """ + Rule that checks for a source with a particular tag. + """ + labels = [ _('Tag:') ] + name = _('Sources with the ') + description = _("Matches sources with the particular tag") diff --git a/gramps/gen/lib/citation.py b/gramps/gen/lib/citation.py index 3be1c145f..090b0fdf9 100644 --- a/gramps/gen/lib/citation.py +++ b/gramps/gen/lib/citation.py @@ -43,6 +43,7 @@ from .primaryobj import PrimaryObject from .mediabase import MediaBase from .notebase import NoteBase from .datebase import DateBase +from .tagbase import TagBase from ..constfunc import cuni from .handle import Handle @@ -91,7 +92,8 @@ class Citation(MediaBase, NoteBase, PrimaryObject, DateBase): MediaBase.serialize(self), # 7 self.datamap, # 8 self.change, # 9 - self.private) # 10 + TagBase.serialize(self), # 10 + self.private) # 11 def to_struct(self): """ @@ -123,7 +125,8 @@ class Citation(MediaBase, NoteBase, PrimaryObject, DateBase): "media_list": MediaBase.to_struct(self), # 7 "datamap": self.datamap, # 8 "change": self.change, # 9 - "private": self.private} # 10 + "tag_list": TagBase.to_struct(self), # 10 + "private": self.private} # 11 def unserialize(self, data): """ @@ -140,12 +143,14 @@ class Citation(MediaBase, NoteBase, PrimaryObject, DateBase): media_list, # 7 self.datamap, # 8 self.change, # 9 - self.private # 10 + tag_list, # 10 + self.private # 11 ) = data DateBase.unserialize(self, date) NoteBase.unserialize(self, note_list) MediaBase.unserialize(self, media_list) + TagBase.unserialize(self, tag_list) return self def _has_handle_reference(self, classname, handle): @@ -244,7 +249,8 @@ class Citation(MediaBase, NoteBase, PrimaryObject, DateBase): :returns: List of (classname, handle) tuples for referenced objects. :rtype: list """ - ret = self.get_referenced_note_handles() + ret = (self.get_referenced_note_handles() + + self.get_referenced_tag_handles()) if self.get_reference_handle(): ret += [('Source', self.get_reference_handle())] return ret @@ -259,6 +265,7 @@ class Citation(MediaBase, NoteBase, PrimaryObject, DateBase): self._merge_privacy(acquisition) self._merge_note_list(acquisition) self._merge_media_list(acquisition) + self._merge_tag_list(acquisition) # merge confidence level_priority = [0, 4, 1, 3, 2] idx = min(level_priority.index(self.confidence), diff --git a/gramps/gen/lib/event.py b/gramps/gen/lib/event.py index 42ebeec9f..653324ca3 100644 --- a/gramps/gen/lib/event.py +++ b/gramps/gen/lib/event.py @@ -46,6 +46,7 @@ from .mediabase import MediaBase from .attrbase import AttributeBase from .datebase import DateBase from .placebase import PlaceBase +from .tagbase import TagBase from .eventtype import EventType from .handle import Handle @@ -116,7 +117,7 @@ class Event(CitationBase, NoteBase, MediaBase, AttributeBase, NoteBase.serialize(self), MediaBase.serialize(self), AttributeBase.serialize(self), - self.change, self.private) + self.change, TagBase.serialize(self), self.private) def to_struct(self): """ @@ -149,6 +150,7 @@ class Event(CitationBase, NoteBase, MediaBase, AttributeBase, "media_list": MediaBase.to_struct(self), "attribute_list": AttributeBase.to_struct(self), "change": self.change, + "tag_list": TagBase.to_struct(self), "private": self.private} def unserialize(self, data): @@ -163,7 +165,7 @@ class Event(CitationBase, NoteBase, MediaBase, AttributeBase, (self.handle, self.gramps_id, the_type, date, self.__description, self.place, citation_list, note_list, media_list, attribute_list, - self.change, self.private) = data + self.change, tag_list, self.private) = data self.__type = EventType() self.__type.unserialize(the_type) @@ -172,6 +174,7 @@ class Event(CitationBase, NoteBase, MediaBase, AttributeBase, AttributeBase.unserialize(self, attribute_list) CitationBase.unserialize(self, citation_list) NoteBase.unserialize(self, note_list) + TagBase.unserialize(self, tag_list) return self def _has_handle_reference(self, classname, handle): @@ -263,8 +266,9 @@ class Event(CitationBase, NoteBase, MediaBase, AttributeBase, :returns: List of (classname, handle) tuples for referenced objects. :rtype: list """ - ret = self.get_referenced_note_handles() + \ - self.get_referenced_citation_handles() + ret = (self.get_referenced_note_handles() + + self.get_referenced_citation_handles() + + self.get_referenced_tag_handles()) if self.place: ret.append(('Place', self.place)) return ret @@ -338,6 +342,7 @@ class Event(CitationBase, NoteBase, MediaBase, AttributeBase, self._merge_note_list(acquisition) self._merge_citation_list(acquisition) self._merge_media_list(acquisition) + self._merge_tag_list(acquisition) def set_type(self, the_type): """ diff --git a/gramps/gen/lib/family.py b/gramps/gen/lib/family.py index 525421237..d1e6da37f 100644 --- a/gramps/gen/lib/family.py +++ b/gramps/gen/lib/family.py @@ -60,7 +60,7 @@ from .handle import Handle # #------------------------------------------------------------------------- class Family(CitationBase, NoteBase, MediaBase, AttributeBase, LdsOrdBase, - TagBase, PrimaryObject): + PrimaryObject): """ The Family record is the GRAMPS in-memory representation of the relationships between people. It contains all the information @@ -91,7 +91,6 @@ class Family(CitationBase, NoteBase, MediaBase, AttributeBase, LdsOrdBase, MediaBase.__init__(self) AttributeBase.__init__(self) LdsOrdBase.__init__(self) - TagBase.__init__(self) self.father_handle = None self.mother_handle = None self.child_ref_list = [] diff --git a/gramps/gen/lib/mediaobj.py b/gramps/gen/lib/mediaobj.py index c42b4b861..279fcb457 100644 --- a/gramps/gen/lib/mediaobj.py +++ b/gramps/gen/lib/mediaobj.py @@ -60,7 +60,7 @@ from .handle import Handle # #------------------------------------------------------------------------- class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase, - TagBase, PrimaryObject): + PrimaryObject): """ Container for information about an image file, including location, description and privacy. @@ -81,7 +81,6 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase, NoteBase.__init__(self, source) DateBase.__init__(self, source) AttributeBase.__init__(self, source) - TagBase.__init__(self) if source: self.path = source.path diff --git a/gramps/gen/lib/note.py b/gramps/gen/lib/note.py index 7e39bb1e4..1d25dc19a 100644 --- a/gramps/gen/lib/note.py +++ b/gramps/gen/lib/note.py @@ -43,7 +43,7 @@ from .handle import Handle # Class for notes used throughout the majority of GRAMPS objects # #------------------------------------------------------------------------- -class Note(BasicPrimaryObject, TagBase): +class Note(BasicPrimaryObject): """Define a text note. Starting from GRAMPS 3.1 Note object stores the text in :class:`gen.lib.styledtext.StyledText` @@ -83,7 +83,6 @@ class Note(BasicPrimaryObject, TagBase): def __init__(self, text=""): """Create a new Note object, initializing from the passed string.""" BasicPrimaryObject.__init__(self) - TagBase.__init__(self) self.text = StyledText(text) self.format = Note.FLOWED self.type = NoteType() diff --git a/gramps/gen/lib/person.py b/gramps/gen/lib/person.py index 3ac13fb20..eeaa261c5 100644 --- a/gramps/gen/lib/person.py +++ b/gramps/gen/lib/person.py @@ -60,7 +60,7 @@ from .handle import Handle # #------------------------------------------------------------------------- class Person(CitationBase, NoteBase, AttributeBase, MediaBase, - AddressBase, UrlBase, LdsOrdBase, TagBase, PrimaryObject): + AddressBase, UrlBase, LdsOrdBase, PrimaryObject): """ The Person record is the GRAMPS in-memory representation of an individual person. It contains all the information related to @@ -98,7 +98,6 @@ class Person(CitationBase, NoteBase, AttributeBase, MediaBase, AddressBase.__init__(self) UrlBase.__init__(self) LdsOrdBase.__init__(self) - TagBase.__init__(self) self.primary_name = Name() self.event_ref_list = [] self.family_list = [] diff --git a/gramps/gen/lib/place.py b/gramps/gen/lib/place.py index 4022c98cf..091cd5980 100644 --- a/gramps/gen/lib/place.py +++ b/gramps/gen/lib/place.py @@ -37,6 +37,7 @@ from .citationbase import CitationBase from .notebase import NoteBase from .mediabase import MediaBase from .urlbase import UrlBase +from .tagbase import TagBase from .location import Location from .handle import Handle @@ -109,7 +110,7 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject): MediaBase.serialize(self), CitationBase.serialize(self), NoteBase.serialize(self), - self.change, self.private) + self.change, TagBase.serialize(self), self.private) def to_struct(self): """ @@ -148,6 +149,7 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject): "citation_list": CitationBase.to_struct(self), "note_list": NoteBase.to_struct(self), "change": self.change, + "tag_list": TagBase.to_struct(self), "private": self.private} def unserialize(self, data): @@ -161,7 +163,7 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject): """ (self.handle, self.gramps_id, self.title, self.long, self.lat, main_loc, alt_loc, urls, media_list, citation_list, note_list, - self.change, self.private) = data + self.change, tag_list, self.private) = data if main_loc is None: self.main_loc = None @@ -172,6 +174,7 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject): MediaBase.unserialize(self, media_list) CitationBase.unserialize(self, citation_list) NoteBase.unserialize(self, note_list) + TagBase.unserialize(self, tag_list) return self def get_text_data_list(self): @@ -233,8 +236,9 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject): :returns: List of (classname, handle) tuples for referenced objects. :rtype: list """ - return self.get_referenced_note_handles() + \ - self.get_referenced_citation_handles() + return (self.get_referenced_note_handles() + + self.get_referenced_citation_handles() + + self.get_referenced_tag_handles()) def merge(self, acquisition): """ Merge the content of acquisition into this place. @@ -248,6 +252,7 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject): self._merge_url_list(acquisition) self._merge_note_list(acquisition) self._merge_citation_list(acquisition) + self._merge_tag_list(acquisition) def set_title(self, title): """ diff --git a/gramps/gen/lib/primaryobj.py b/gramps/gen/lib/primaryobj.py index c995c0b77..e21387ad3 100644 --- a/gramps/gen/lib/primaryobj.py +++ b/gramps/gen/lib/primaryobj.py @@ -34,13 +34,14 @@ from .tableobj import TableObject from .privacybase import PrivacyBase from .citationbase import CitationBase from .mediabase import MediaBase +from .tagbase import TagBase #------------------------------------------------------------------------- # # Basic Primary Object class # #------------------------------------------------------------------------- -class BasicPrimaryObject(TableObject, PrivacyBase): +class BasicPrimaryObject(TableObject, PrivacyBase, TagBase): """ The BasicPrimaryObject is the base class for Note objects. @@ -66,6 +67,7 @@ class BasicPrimaryObject(TableObject, PrivacyBase): """ TableObject.__init__(self, source) PrivacyBase.__init__(self, source) + TagBase.__init__(self) if source: self.gramps_id = source.gramps_id else: diff --git a/gramps/gen/lib/repo.py b/gramps/gen/lib/repo.py index 648e6abae..89dd5d0e4 100644 --- a/gramps/gen/lib/repo.py +++ b/gramps/gen/lib/repo.py @@ -35,6 +35,7 @@ from .primaryobj import PrimaryObject from .notebase import NoteBase from .addressbase import AddressBase from .urlbase import UrlBase +from .tagbase import TagBase from .repotype import RepositoryType from ..constfunc import cuni from .handle import Handle @@ -67,7 +68,7 @@ class Repository(NoteBase, AddressBase, UrlBase, PrimaryObject): NoteBase.serialize(self), AddressBase.serialize(self), UrlBase.serialize(self), - self.change, self.private) + self.change, TagBase.serialize(self), self.private) def to_struct(self): """ @@ -97,6 +98,7 @@ class Repository(NoteBase, AddressBase, UrlBase, PrimaryObject): "address_list": AddressBase.to_struct(self), "urls": UrlBase.to_struct(self), "change": self.change, + "tag_list": TagBase.to_struct(self), "private": self.private} def unserialize(self, data): @@ -105,13 +107,14 @@ class Repository(NoteBase, AddressBase, UrlBase, PrimaryObject): back into the data in a Repository structure. """ (self.handle, self.gramps_id, the_type, self.name, note_list, - address_list, urls, self.change, self.private) = data + address_list, urls, self.change, tag_list, self.private) = data self.type = RepositoryType() self.type.unserialize(the_type) NoteBase.unserialize(self, note_list) AddressBase.unserialize(self, address_list) UrlBase.unserialize(self, urls) + TagBase.unserialize(self, tag_list) return self def get_text_data_list(self): @@ -170,7 +173,8 @@ class Repository(NoteBase, AddressBase, UrlBase, PrimaryObject): :returns: List of (classname, handle) tuples for referenced objects. :rtype: list """ - return self.get_referenced_note_handles() + return (self.get_referenced_note_handles() + + self.get_referenced_tag_handles()) def has_citation_reference(self, citation_handle) : """ @@ -236,6 +240,7 @@ class Repository(NoteBase, AddressBase, UrlBase, PrimaryObject): self._merge_address_list(acquisition) self._merge_url_list(acquisition) self._merge_note_list(acquisition) + self._merge_tag_list(acquisition) def set_type(self, the_type): """ diff --git a/gramps/gen/lib/src.py b/gramps/gen/lib/src.py index 3b4c916de..dde995b38 100644 --- a/gramps/gen/lib/src.py +++ b/gramps/gen/lib/src.py @@ -34,6 +34,7 @@ Source object for GRAMPS. from .primaryobj import PrimaryObject from .mediabase import MediaBase from .notebase import NoteBase +from .tagbase import TagBase from .reporef import RepoRef from .const import DIFFERENT, EQUAL, IDENTICAL from ..constfunc import cuni @@ -69,7 +70,7 @@ class Source(MediaBase, NoteBase, PrimaryObject): MediaBase.serialize(self), cuni(self.abbrev), self.change, self.datamap, [rr.serialize() for rr in self.reporef_list], - self.private) + TagBase.serialize(self), self.private) def to_struct(self): """ @@ -102,6 +103,7 @@ class Source(MediaBase, NoteBase, PrimaryObject): "change": self.change, "datamap": {"dict": self.datamap}, "reporef_list": [rr.to_struct() for rr in self.reporef_list], + "tag_list": TagBase.to_struct(self), "private": self.private} def unserialize(self, data): @@ -112,10 +114,11 @@ class Source(MediaBase, NoteBase, PrimaryObject): (self.handle, self.gramps_id, self.title, self.author, self.pubinfo, note_list, media_list, self.abbrev, self.change, self.datamap, reporef_list, - self.private) = data + tag_list, self.private) = data NoteBase.unserialize(self, note_list) MediaBase.unserialize(self, media_list) + TagBase.unserialize(self, tag_list) self.reporef_list = [RepoRef().unserialize(item) for item in reporef_list] return self @@ -225,7 +228,8 @@ class Source(MediaBase, NoteBase, PrimaryObject): :returns: List of (classname, handle) tuples for referenced objects. :rtype: list """ - return self.get_referenced_note_handles() + return (self.get_referenced_note_handles() + + self.get_referenced_tag_handles()) def merge(self, acquisition): """ @@ -237,6 +241,7 @@ class Source(MediaBase, NoteBase, PrimaryObject): self._merge_privacy(acquisition) self._merge_note_list(acquisition) self._merge_media_list(acquisition) + self._merge_tag_list(acquisition) my_datamap = self.get_data_map() acquisition_map = acquisition.get_data_map() for key in acquisition.get_data_map(): diff --git a/gramps/gui/editors/editcitation.py b/gramps/gui/editors/editcitation.py index 55c020208..32d9a07e4 100644 --- a/gramps/gui/editors/editcitation.py +++ b/gramps/gui/editors/editcitation.py @@ -46,9 +46,9 @@ from gramps.gen.db import DbTxn from .editprimary import EditPrimary from .displaytabs import (NoteTab, GalleryTab, DataEmbedList, - SourceBackRefList, RepoEmbedList, CitationBackRefList) + SourceBackRefList, RepoEmbedList, CitationBackRefList) from ..widgets import (MonitoredEntry, PrivacyButton, MonitoredMenu, - MonitoredDate) + MonitoredDate, MonitoredTagList) from ..dialog import ErrorDialog from .editreference import RefTab from ..glade import Glade @@ -277,6 +277,15 @@ class EditCitation(EditPrimary): (_('Very High'), Citation.CONF_VERY_HIGH)], self.db.readonly) + self.tags2 = MonitoredTagList( + self.glade.get_object("tag_label2"), + self.glade.get_object("tag_button2"), + self.obj.set_tag_list, + self.obj.get_tag_list, + self.db, + self.uistate, self.track, + self.db.readonly) + self.ref_privacy = PrivacyButton( self.glade.get_object('privacy'), self.obj, self.db.readonly) @@ -296,6 +305,15 @@ class EditCitation(EditPrimary): self.glade.get_object('gid'), self.source.set_gramps_id, self.source.get_gramps_id,self.db.readonly) + self.tags = MonitoredTagList( + self.glade.get_object("tag_label"), + self.glade.get_object("tag_button"), + self.source.set_tag_list, + self.source.get_tag_list, + self.db, + self.uistate, self.track, + self.db.readonly) + self.source_privacy = PrivacyButton( self.glade.get_object("private"), self.source, self.db.readonly) diff --git a/gramps/gui/editors/editevent.py b/gramps/gui/editors/editevent.py index 25867f2b4..19e4e6f34 100644 --- a/gramps/gui/editors/editevent.py +++ b/gramps/gui/editors/editevent.py @@ -51,9 +51,9 @@ from .objectentries import PlaceEntry from ..glade import Glade from ..dialog import ErrorDialog from .displaytabs import (CitationEmbedList, NoteTab, GalleryTab, - EventBackRefList, AttrEmbedList) -from ..widgets import (MonitoredEntry, PrivacyButton, - MonitoredDataType, MonitoredDate) + EventBackRefList, AttrEmbedList) +from ..widgets import (MonitoredEntry, PrivacyButton, MonitoredDataType, + MonitoredDate, MonitoredTagList) from gramps.gen.utils.db import get_participant_from_event #------------------------------------------------------------------------- @@ -153,8 +153,16 @@ class EditEvent(EditPrimary): self.obj.set_gramps_id, self.obj.get_gramps_id, self.db.readonly) - self.priv = PrivacyButton( self.top.get_object("private"), - self.obj, self.db.readonly) + self.tags = MonitoredTagList(self.top.get_object("tag_label"), + self.top.get_object("tag_button"), + self.obj.set_tag_list, + self.obj.get_tag_list, + self.db, + self.uistate, self.track, + self.db.readonly) + + self.priv = PrivacyButton(self.top.get_object("private"), + self.obj, self.db.readonly) self.event_menu = MonitoredDataType(self.top.get_object("personal_events"), self.obj.set_type, diff --git a/gramps/gui/editors/editplace.py b/gramps/gui/editors/editplace.py index cf1fa6a06..374f69053 100644 --- a/gramps/gui/editors/editplace.py +++ b/gramps/gui/editors/editplace.py @@ -52,7 +52,7 @@ from gramps.gen.db import DbTxn from .editprimary import EditPrimary from .displaytabs import (GrampsTab, LocationEmbedList, CitationEmbedList, GalleryTab, NoteTab, WebEmbedList, PlaceBackRefList) -from ..widgets import MonitoredEntry, PrivacyButton +from ..widgets import MonitoredEntry, PrivacyButton, MonitoredTagList from gramps.gen.errors import ValidationError from gramps.gen.utils.place import conv_lat_lon from ..dialog import ErrorDialog @@ -177,6 +177,14 @@ class EditPlace(EditPrimary): self.obj.set_gramps_id, self.obj.get_gramps_id, self.db.readonly) + self.tags = MonitoredTagList(self.top.get_object("tag_label"), + self.top.get_object("tag_button"), + self.obj.set_tag_list, + self.obj.get_tag_list, + self.db, + self.uistate, self.track, + self.db.readonly) + self.privacy = PrivacyButton(self.top.get_object("private"), self.obj, self.db.readonly) diff --git a/gramps/gui/editors/editrepository.py b/gramps/gui/editors/editrepository.py index 6826ce80c..9b599cc04 100644 --- a/gramps/gui/editors/editrepository.py +++ b/gramps/gui/editors/editrepository.py @@ -44,7 +44,8 @@ from gi.repository import Gtk from gramps.gen.lib import NoteType, Repository from gramps.gen.db import DbTxn -from ..widgets import MonitoredEntry, MonitoredDataType, PrivacyButton +from ..widgets import (MonitoredEntry, MonitoredDataType, PrivacyButton, + MonitoredTagList) from .displaytabs import AddrEmbedList, WebEmbedList, NoteTab, SourceBackRefList from .editprimary import EditPrimary from ..dialog import ErrorDialog @@ -93,14 +94,21 @@ class EditRepository(EditPrimary): self.type = MonitoredDataType(self.glade.get_object("repository_type"), self.obj.set_type, self.obj.get_type, self.db.readonly, - self.db.get_repository_types(), - ) + self.db.get_repository_types()) self.call_number = MonitoredEntry(self.glade.get_object('gid'), self.obj.set_gramps_id, self.obj.get_gramps_id, self.db.readonly) + self.tags = MonitoredTagList(self.glade.get_object("tag_label"), + self.glade.get_object("tag_button"), + self.obj.set_tag_list, + self.obj.get_tag_list, + self.db, + self.uistate, self.track, + self.db.readonly) + self.privacy = PrivacyButton(self.glade.get_object("private"), self.obj, self.db.readonly) diff --git a/gramps/gui/editors/editsource.py b/gramps/gui/editors/editsource.py index 5421a5bdf..8f88f3905 100644 --- a/gramps/gui/editors/editsource.py +++ b/gramps/gui/editors/editsource.py @@ -50,8 +50,8 @@ from gramps.gen.db import DbTxn from .editprimary import EditPrimary from .displaytabs import (NoteTab, GalleryTab, DataEmbedList, - CitationBackRefList, RepoEmbedList) -from ..widgets import MonitoredEntry, PrivacyButton + CitationBackRefList, RepoEmbedList) +from ..widgets import MonitoredEntry, PrivacyButton, MonitoredTagList from ..dialog import ErrorDialog from ..glade import Glade @@ -116,6 +116,14 @@ class EditSource(EditPrimary): self.obj.set_gramps_id, self.obj.get_gramps_id, self.db.readonly) + self.tags = MonitoredTagList(self.glade.get_object("tag_label"), + self.glade.get_object("tag_button"), + self.obj.set_tag_list, + self.obj.get_tag_list, + self.db, + self.uistate, self.track, + self.db.readonly) + self.priv = PrivacyButton(self.glade.get_object("private"), self.obj, self.db.readonly) diff --git a/gramps/gui/filters/sidebar/_citationsidebarfilter.py b/gramps/gui/filters/sidebar/_citationsidebarfilter.py index 20427c698..9ed332d94 100644 --- a/gramps/gui/filters/sidebar/_citationsidebarfilter.py +++ b/gramps/gui/filters/sidebar/_citationsidebarfilter.py @@ -49,7 +49,7 @@ from gramps.gen.constfunc import cuni from gramps.gen.filters import GenericFilterFactory, rules from gramps.gen.filters.rules.citation import (RegExpIdOf, HasIdOf, HasCitation, HasNoteMatchingSubstringOf, - HasNoteRegexp, MatchesFilter) + HasNoteRegexp, MatchesFilter, HasTag) from gramps.gen.utils.string import confidence GenericCitationFilter = GenericFilterFactory('Citation') #------------------------------------------------------------------------- @@ -76,6 +76,7 @@ class CitationSidebarFilter(SidebarFilter): self.filter_regex = Gtk.CheckButton(_('Use regular expressions')) + self.tag = Gtk.ComboBox() self.generic = Gtk.ComboBox() SidebarFilter.__init__(self, dbstate, uistate, "Citation") @@ -94,11 +95,18 @@ class CitationSidebarFilter(SidebarFilter): self.filter_conf.pack_start(cell, True) self.filter_conf.add_attribute(cell, 'text', 0) + cell = Gtk.CellRendererText() + cell.set_property('width', self._FILTER_WIDTH) + cell.set_property('ellipsize', self._FILTER_ELLIPSIZE) + self.tag.pack_start(cell, True) + self.tag.add_attribute(cell, 'text', 0) + self.add_text_entry(_('ID'), self.filter_id) self.add_text_entry(_('Volume/Page'), self.filter_page) self.add_text_entry(_('Date'), self.filter_date) self.add_entry(_('Confidence'), self.filter_conf) self.add_text_entry(_('Note'), self.filter_note) + self.add_entry(_('Tag'), self.tag) self.add_filter_entry(_('Custom filter'), self.generic) self.add_entry(None, self.filter_regex) @@ -108,6 +116,7 @@ class CitationSidebarFilter(SidebarFilter): self.filter_date.set_text('') self.filter_conf.set_active(2) self.filter_note.set_text('') + self.tag.set_active(0) self.generic.set_active(0) def get_filter(self): @@ -125,9 +134,10 @@ class CitationSidebarFilter(SidebarFilter): # conf = self.citn.get_confidence_level() note = cuni(self.filter_note.get_text()).strip() regex = self.filter_regex.get_active() + tag = self.tag.get_active() > 0 gen = self.generic.get_active() > 0 - empty = not (gid or page or date or conf or note or regex or gen) + empty = not (gid or page or date or conf or note or regex or tag or gen) if empty: generic_filter = None else: @@ -149,12 +159,20 @@ class CitationSidebarFilter(SidebarFilter): rule = HasNoteMatchingSubstringOf([note]) generic_filter.add_rule(rule) - if self.generic.get_active() != 0: - model = self.generic.get_model() - node = self.generic.get_active_iter() - obj = cuni(model.get_value(node, 0)) - rule = MatchesFilter([obj]) - generic_filter.add_rule(rule) + # check the Tag + if tag: + model = self.tag.get_model() + node = self.tag.get_active_iter() + attr = model.get_value(node, 0) + rule = HasTag([attr]) + generic_filter.add_rule(rule) + + if self.generic.get_active() != 0: + model = self.generic.get_model() + node = self.generic.get_active_iter() + obj = cuni(model.get_value(node, 0)) + rule = MatchesFilter([obj]) + generic_filter.add_rule(rule) return generic_filter @@ -165,3 +183,14 @@ class CitationSidebarFilter(SidebarFilter): all_filter.add_rule(rules.citation.AllCitations([])) self.generic.set_model(build_filter_model('Citation', [all_filter])) self.generic.set_active(0) + + def on_tags_changed(self, tag_list): + """ + Update the list of tags in the tag filter. + """ + model = Gtk.ListStore(str) + model.append(('',)) + for tag_name in tag_list: + model.append((tag_name,)) + self.tag.set_model(model) + self.tag.set_active(0) diff --git a/gramps/gui/filters/sidebar/_eventsidebarfilter.py b/gramps/gui/filters/sidebar/_eventsidebarfilter.py index 20b0efa3e..a5179d2df 100644 --- a/gramps/gui/filters/sidebar/_eventsidebarfilter.py +++ b/gramps/gui/filters/sidebar/_eventsidebarfilter.py @@ -48,7 +48,7 @@ from gramps.gen.constfunc import cuni from gramps.gen.filters import GenericFilterFactory, rules from gramps.gen.filters.rules.event import (RegExpIdOf, HasIdOf, HasNoteRegexp, HasNoteMatchingSubstringOf, MatchesFilter, - HasEvent) + HasEvent, HasTag) GenericEventFilter = GenericFilterFactory('Event') #------------------------------------------------------------------------- @@ -78,6 +78,7 @@ class EventSidebarFilter(SidebarFilter): self.filter_regex = Gtk.CheckButton(_('Use regular expressions')) + self.tag = Gtk.ComboBox() self.generic = Gtk.ComboBox() SidebarFilter.__init__(self, dbstate, uistate, "Event") @@ -90,6 +91,12 @@ class EventSidebarFilter(SidebarFilter): self.generic.add_attribute(cell, 'text', 0) self.on_filters_changed('Event') + cell = Gtk.CellRendererText() + cell.set_property('width', self._FILTER_WIDTH) + cell.set_property('ellipsize', self._FILTER_ELLIPSIZE) + self.tag.pack_start(cell, True) + self.tag.add_attribute(cell, 'text', 0) + self.etype.get_child().set_width_chars(5) self.add_text_entry(_('ID'), self.filter_id) @@ -99,6 +106,7 @@ class EventSidebarFilter(SidebarFilter): self.add_text_entry(_('Date'), self.filter_date) self.add_text_entry(_('Place'), self.filter_place) self.add_text_entry(_('Note'), self.filter_note) + self.add_entry(_('Tag'), self.tag) self.add_filter_entry(_('Custom filter'), self.generic) self.add_regex_entry(self.filter_regex) @@ -110,6 +118,7 @@ class EventSidebarFilter(SidebarFilter): self.filter_place.set_text('') self.filter_note.set_text('') self.etype.get_child().set_text('') + self.tag.set_active(0) self.generic.set_active(0) def get_filter(self): @@ -120,11 +129,12 @@ class EventSidebarFilter(SidebarFilter): place = cuni(self.filter_place.get_text()).strip() note = cuni(self.filter_note.get_text()).strip() regex = self.filter_regex.get_active() + tag = self.tag.get_active() > 0 generic = self.generic.get_active() > 0 etype = self.filter_event.get_type().xml_str() empty = not (gid or desc or mainparts or date or place or note - or etype or regex or generic) + or etype or regex or tag or generic) if empty: generic_filter = None else: @@ -147,12 +157,20 @@ class EventSidebarFilter(SidebarFilter): rule = HasNoteMatchingSubstringOf([note]) generic_filter.add_rule(rule) - if self.generic.get_active() != 0: - model = self.generic.get_model() - node = self.generic.get_active_iter() - obj = cuni(model.get_value(node, 0)) - rule = MatchesFilter([obj]) - generic_filter.add_rule(rule) + # check the Tag + if tag: + model = self.tag.get_model() + node = self.tag.get_active_iter() + attr = model.get_value(node, 0) + rule = HasTag([attr]) + generic_filter.add_rule(rule) + + if self.generic.get_active() != 0: + model = self.generic.get_model() + node = self.generic.get_active_iter() + obj = cuni(model.get_value(node, 0)) + rule = MatchesFilter([obj]) + generic_filter.add_rule(rule) return generic_filter @@ -163,3 +181,14 @@ class EventSidebarFilter(SidebarFilter): all_filter.add_rule(rules.event.AllEvents([])) self.generic.set_model(build_filter_model('Event', [all_filter])) self.generic.set_active(0) + + def on_tags_changed(self, tag_list): + """ + Update the list of tags in the tag filter. + """ + model = Gtk.ListStore(str) + model.append(('',)) + for tag_name in tag_list: + model.append((tag_name,)) + self.tag.set_model(model) + self.tag.set_active(0) diff --git a/gramps/gui/filters/sidebar/_placesidebarfilter.py b/gramps/gui/filters/sidebar/_placesidebarfilter.py index 1a4555b46..13c5a0fff 100644 --- a/gramps/gui/filters/sidebar/_placesidebarfilter.py +++ b/gramps/gui/filters/sidebar/_placesidebarfilter.py @@ -49,7 +49,7 @@ from gramps.gen.constfunc import cuni from gramps.gen.filters import GenericFilterFactory, rules from gramps.gen.filters.rules.place import (RegExpIdOf, HasIdOf, HasPlace, HasNoteRegexp, HasNoteMatchingSubstringOf, - MatchesFilter) + MatchesFilter, HasTag) GenericPlaceFilter = GenericFilterFactory('Place') #------------------------------------------------------------------------- @@ -75,6 +75,7 @@ class PlaceSidebarFilter(SidebarFilter): self.filter_note = widgets.BasicEntry() self.filter_regex = Gtk.CheckButton(_('Use regular expressions')) + self.tag = Gtk.ComboBox() self.generic = Gtk.ComboBox() SidebarFilter.__init__(self, dbstate, uistate, "Place") @@ -87,6 +88,12 @@ class PlaceSidebarFilter(SidebarFilter): self.generic.add_attribute(cell, 'text', 0) self.on_filters_changed('Place') + cell = Gtk.CellRendererText() + cell.set_property('width', self._FILTER_WIDTH) + cell.set_property('ellipsize', self._FILTER_ELLIPSIZE) + self.tag.pack_start(cell, True) + self.tag.add_attribute(cell, 'text', 0) + self.add_text_entry(_('ID'), self.filter_id) self.add_text_entry(_('Place Name'), self.filter_title) self.add_text_entry(_('Street'), self.filter_street) @@ -98,6 +105,7 @@ class PlaceSidebarFilter(SidebarFilter): self.add_text_entry(_('ZIP/Postal code'), self.filter_zip) self.add_text_entry(_('Church parish'), self.filter_parish) self.add_text_entry(_('Note'), self.filter_note) + self.add_entry(_('Tag'), self.tag) self.add_filter_entry(_('Custom filter'), self.generic) self.add_regex_entry(self.filter_regex) @@ -113,6 +121,7 @@ class PlaceSidebarFilter(SidebarFilter): self.filter_zip.set_text('') self.filter_parish.set_text('') self.filter_note.set_text('') + self.tag.set_active(0) self.generic.set_active(0) def get_filter(self): @@ -128,10 +137,12 @@ class PlaceSidebarFilter(SidebarFilter): parish = cuni(self.filter_parish.get_text()).strip() note = cuni(self.filter_note.get_text()).strip() regex = self.filter_regex.get_active() + tag = self.tag.get_active() > 0 gen = self.generic.get_active() > 0 empty = not (gid or title or street or locality or city or county or - state or country or zipc or parish or note or regex or gen) + state or country or zipc or parish or note or regex or tag + or gen) if empty: generic_filter = None else: @@ -154,6 +165,14 @@ class PlaceSidebarFilter(SidebarFilter): rule = HasNoteMatchingSubstringOf([note]) generic_filter.add_rule(rule) + # check the Tag + if tag: + model = self.tag.get_model() + node = self.tag.get_active_iter() + attr = model.get_value(node, 0) + rule = HasTag([attr]) + generic_filter.add_rule(rule) + if self.generic.get_active() != 0: model = self.generic.get_model() node = self.generic.get_active_iter() @@ -170,3 +189,14 @@ class PlaceSidebarFilter(SidebarFilter): all_filter.add_rule(rules.place.AllPlaces([])) self.generic.set_model(build_filter_model('Place', [all_filter])) self.generic.set_active(0) + + def on_tags_changed(self, tag_list): + """ + Update the list of tags in the tag filter. + """ + model = Gtk.ListStore(str) + model.append(('',)) + for tag_name in tag_list: + model.append((tag_name,)) + self.tag.set_model(model) + self.tag.set_active(0) diff --git a/gramps/gui/filters/sidebar/_reposidebarfilter.py b/gramps/gui/filters/sidebar/_reposidebarfilter.py index ea8d28116..c5add6d63 100644 --- a/gramps/gui/filters/sidebar/_reposidebarfilter.py +++ b/gramps/gui/filters/sidebar/_reposidebarfilter.py @@ -48,7 +48,7 @@ from gramps.gen.constfunc import cuni from gramps.gen.filters import GenericFilterFactory, rules from gramps.gen.filters.rules.repository import (RegExpIdOf, HasIdOf, HasRepo, HasNoteRegexp, MatchesFilter, - HasNoteMatchingSubstringOf) + HasNoteMatchingSubstringOf, HasTag) GenericRepoFilter = GenericFilterFactory('Repository') #------------------------------------------------------------------------- @@ -77,6 +77,7 @@ class RepoSidebarFilter(SidebarFilter): self.filter_regex = Gtk.CheckButton(_('Use regular expressions')) + self.tag = Gtk.ComboBox() self.generic = Gtk.ComboBox() SidebarFilter.__init__(self, dbstate, uistate, "Repository") @@ -89,6 +90,12 @@ class RepoSidebarFilter(SidebarFilter): self.generic.add_attribute(cell, 'text', 0) self.on_filters_changed('Repository') + cell = Gtk.CellRendererText() + cell.set_property('width', self._FILTER_WIDTH) + cell.set_property('ellipsize', self._FILTER_ELLIPSIZE) + self.tag.pack_start(cell, True) + self.tag.add_attribute(cell, 'text', 0) + self.rtype.get_child().set_width_chars(5) self.add_text_entry(_('ID'), self.filter_id) @@ -97,6 +104,7 @@ class RepoSidebarFilter(SidebarFilter): self.add_text_entry(_('Address'), self.filter_address) self.add_text_entry(_('URL'), self.filter_url) self.add_text_entry(_('Note'), self.filter_note) + self.add_entry(_('Tag'), self.tag) self.add_filter_entry(_('Custom filter'), self.generic) self.add_regex_entry(self.filter_regex) @@ -107,6 +115,7 @@ class RepoSidebarFilter(SidebarFilter): self.filter_url.set_text('') self.rtype.get_child().set_text('') self.filter_note.set_text('') + self.tag.set_active(0) self.generic.set_active(0) def get_filter(self): @@ -117,10 +126,11 @@ class RepoSidebarFilter(SidebarFilter): rtype = self.repo.get_type().xml_str() note = cuni(self.filter_note.get_text()).strip() regex = self.filter_regex.get_active() + tag = self.tag.get_active() > 0 gen = self.generic.get_active() > 0 empty = not (gid or title or address or url or rtype - or note or regex or gen) + or note or regex or tag or gen) if empty: generic_filter = None else: @@ -142,12 +152,20 @@ class RepoSidebarFilter(SidebarFilter): rule = HasNoteMatchingSubstringOf([note]) generic_filter.add_rule(rule) - if self.generic.get_active() != 0: - model = self.generic.get_model() - node = self.generic.get_active_iter() - obj = cuni(model.get_value(node, 0)) - rule = MatchesFilter([obj]) - generic_filter.add_rule(rule) + # check the Tag + if tag: + model = self.tag.get_model() + node = self.tag.get_active_iter() + attr = model.get_value(node, 0) + rule = HasTag([attr]) + generic_filter.add_rule(rule) + + if self.generic.get_active() != 0: + model = self.generic.get_model() + node = self.generic.get_active_iter() + obj = cuni(model.get_value(node, 0)) + rule = MatchesFilter([obj]) + generic_filter.add_rule(rule) return generic_filter @@ -159,3 +177,14 @@ class RepoSidebarFilter(SidebarFilter): self.generic.set_model(build_filter_model('Repository', [all_filter])) self.generic.set_active(0) + + def on_tags_changed(self, tag_list): + """ + Update the list of tags in the tag filter. + """ + model = Gtk.ListStore(str) + model.append(('',)) + for tag_name in tag_list: + model.append((tag_name,)) + self.tag.set_model(model) + self.tag.set_active(0) diff --git a/gramps/gui/filters/sidebar/_sourcesidebarfilter.py b/gramps/gui/filters/sidebar/_sourcesidebarfilter.py index 8bea42ce7..578ad0e49 100644 --- a/gramps/gui/filters/sidebar/_sourcesidebarfilter.py +++ b/gramps/gui/filters/sidebar/_sourcesidebarfilter.py @@ -47,7 +47,7 @@ from gramps.gen.constfunc import cuni from gramps.gen.filters import GenericFilterFactory, rules from gramps.gen.filters.rules.source import (RegExpIdOf, HasIdOf, HasSource, HasNoteMatchingSubstringOf, - HasNoteRegexp, MatchesFilter) + HasNoteRegexp, MatchesFilter, HasTag) GenericSourceFilter = GenericFilterFactory('Source') #------------------------------------------------------------------------- @@ -68,6 +68,7 @@ class SourceSidebarFilter(SidebarFilter): self.filter_regex = Gtk.CheckButton(_('Use regular expressions')) + self.tag = Gtk.ComboBox() self.generic = Gtk.ComboBox() SidebarFilter.__init__(self, dbstate, uistate, "Source") @@ -80,12 +81,19 @@ class SourceSidebarFilter(SidebarFilter): self.generic.add_attribute(cell, 'text', 0) self.on_filters_changed('Source') + cell = Gtk.CellRendererText() + cell.set_property('width', self._FILTER_WIDTH) + cell.set_property('ellipsize', self._FILTER_ELLIPSIZE) + self.tag.pack_start(cell, True) + self.tag.add_attribute(cell, 'text', 0) + self.add_text_entry(_('ID'), self.filter_id) self.add_text_entry(_('Title'), self.filter_title) self.add_text_entry(_('Author'), self.filter_author) self.add_text_entry(_('Abbreviation'), self.filter_abbr) self.add_text_entry(_('Publication'), self.filter_pub) self.add_text_entry(_('Note'), self.filter_note) + self.add_entry(_('Tag'), self.tag) self.add_filter_entry(_('Custom filter'), self.generic) self.add_regex_entry(self.filter_regex) @@ -96,6 +104,7 @@ class SourceSidebarFilter(SidebarFilter): self.filter_abbr.set_text('') self.filter_pub.set_text('') self.filter_note.set_text('') + self.tag.set_active(0) self.generic.set_active(0) def get_filter(self): @@ -106,10 +115,11 @@ class SourceSidebarFilter(SidebarFilter): pub = cuni(self.filter_pub.get_text()).strip() note = cuni(self.filter_note.get_text()).strip() regex = self.filter_regex.get_active() + tag = self.tag.get_active() > 0 gen = self.generic.get_active() > 0 - empty = not (gid or title or author or abbr or pub or note or regex or - gen) + empty = not (gid or title or author or abbr or pub or note or regex + or tag or gen) if empty: generic_filter = None else: @@ -131,12 +141,20 @@ class SourceSidebarFilter(SidebarFilter): rule = HasNoteMatchingSubstringOf([note]) generic_filter.add_rule(rule) - if self.generic.get_active() != 0: - model = self.generic.get_model() - node = self.generic.get_active_iter() - obj = cuni(model.get_value(node, 0)) - rule = MatchesFilter([obj]) - generic_filter.add_rule(rule) + # check the Tag + if tag: + model = self.tag.get_model() + node = self.tag.get_active_iter() + attr = model.get_value(node, 0) + rule = HasTag([attr]) + generic_filter.add_rule(rule) + + if self.generic.get_active() != 0: + model = self.generic.get_model() + node = self.generic.get_active_iter() + obj = cuni(model.get_value(node, 0)) + rule = MatchesFilter([obj]) + generic_filter.add_rule(rule) return generic_filter @@ -147,3 +165,14 @@ class SourceSidebarFilter(SidebarFilter): all_filter.add_rule(rules.source.AllSources([])) self.generic.set_model(build_filter_model('Source', [all_filter])) self.generic.set_active(0) + + def on_tags_changed(self, tag_list): + """ + Update the list of tags in the tag filter. + """ + model = Gtk.ListStore(str) + model.append(('',)) + for tag_name in tag_list: + model.append((tag_name,)) + self.tag.set_model(model) + self.tag.set_active(0) diff --git a/gramps/gui/glade/editcitation.glade b/gramps/gui/glade/editcitation.glade index 96173c944..4aa36e109 100644 --- a/gramps/gui/glade/editcitation.glade +++ b/gramps/gui/glade/editcitation.glade @@ -23,12 +23,10 @@ gtk-help - False True True True True - False True @@ -40,12 +38,10 @@ gtk-cancel - False True True True True - False True @@ -57,12 +53,10 @@ gtk-ok - False True True True True - False True @@ -114,12 +108,6 @@ - - - - - - True @@ -137,13 +125,11 @@ - False True True True True Invoke date editor - False none @@ -181,8 +167,8 @@ 1 2 - 2 - 3 + 1 + 2 @@ -197,8 +183,8 @@ volume - 2 - 3 + 1 + 2 GTK_FILL @@ -214,8 +200,8 @@ confidence - 3 - 4 + 2 + 3 GTK_FILL @@ -240,8 +226,8 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

1 2 - 3 - 4 + 2 + 3 GTK_FILL
@@ -308,59 +294,53 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

True False - 12 + 6 + 75 True True A unique ID to identify the citation + 6 - True + False True 0 - - False + True - True - True - False - none - - - - Private - - - - - True - False - gtk-dialog-authentication - - - Privacy - - - - + False + 0 + Tags: False - False + True 1 + + + True + False + 0 + + + True + True + 2 + + 1 2 - 1 - 2 + 3 + 4 GTK_FILL @@ -375,12 +355,63 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

gid2 - 1 - 2 + 3 + 4 GTK_FILL
+ + + True + True + True + none + + + + Private + + + + + True + False + gtk-dialog-authentication + + + Privacy + + + + + + + 2 + 3 + 2 + 3 + + + + + + + True + True + True + True + 0 + + + 2 + 3 + 3 + 4 + + + +
@@ -419,7 +450,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

False 12 6 - 2 + 3 12 6 @@ -483,8 +514,8 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

pub_info - 4 - 5 + 2 + 3 GTK_FILL @@ -498,7 +529,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

1 - 2 + 3 1 2 @@ -542,7 +573,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

- 2 + 3 5 6 GTK_EXPAND | GTK_SHRINK | GTK_FILL @@ -573,9 +604,9 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

1 - 2 - 4 - 5 + 3 + 2 + 3
@@ -589,8 +620,8 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

gid - 2 - 3 + 4 + 5 GTK_FILL @@ -601,47 +632,54 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

False 12 - + True - True - A unique ID to identify the source - + False + 6 + + + 75 + True + True + A unique ID to identify the source + + 6 + + + False + True + 0 + + + + + True + False + 0 + Tags: + + + False + True + 1 + + + + + True + False + 0 + + + True + True + 2 + + True True - 0 - - - - - False - True - True - True - False - none - - - Private - - - - - True - False - gtk-dialog-authentication - - - Privacy - - - - - - - False - False 1 @@ -649,8 +687,8 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

1 2 - 2 - 3 + 4 + 5 GTK_FILL @@ -664,7 +702,56 @@ Very High =Direct and primary evidence used, or by dominance of the evidence

1 - 2 + 3 + + + + + + True + True + True + none + + + Private + + + + + True + False + gtk-dialog-authentication + + + Privacy + + + + + + + 2 + 3 + 3 + 4 + + + + + + + True + True + True + True + + + 2 + 3 + 4 + 5 + diff --git a/gramps/gui/glade/editevent.glade b/gramps/gui/glade/editevent.glade index a2159849e..64011219e 100644 --- a/gramps/gui/glade/editevent.glade +++ b/gramps/gui/glade/editevent.glade @@ -17,7 +17,6 @@ gtk-cancel - False True True True @@ -26,7 +25,6 @@ True Close window without changes Close window without changes - False True @@ -38,7 +36,6 @@ gtk-ok - False True True True @@ -46,7 +43,6 @@ True Accept changes and close window Accept changes and close window - False True @@ -58,12 +54,10 @@ gtk-help - False True True True True - False True @@ -93,9 +87,6 @@ 5 12 4 - - - True @@ -108,7 +99,7 @@ GTK_FILL - + @@ -125,18 +116,16 @@ 2 3 GTK_FILL - + - False True True True True Invoke date editor - False none @@ -166,7 +155,7 @@ 4 5 GTK_FILL - + @@ -183,43 +172,7 @@ 1 2 GTK_FILL - - - - - - False - True - True - True - False - none - - - - Private - - - - - True - False - gtk-dialog-authentication - - - Privacy - - - - - - - 4 - 5 - 2 - 3 - GTK_FILL - + @@ -234,7 +187,7 @@ 4 1 2 - + @@ -249,19 +202,17 @@ select_place - 3 - 4 + 2 + 3 GTK_FILL - + - False True True True - False none @@ -274,10 +225,10 @@ 4 5 - 3 - 4 + 2 + 3 GTK_FILL - + @@ -299,11 +250,9 @@ - False True True True - False none @@ -337,8 +286,8 @@ 1 4 - 3 - 4 + 2 + 3 GTK_FILL GTK_FILL @@ -360,7 +309,7 @@ 1 2 GTK_FILL - + @@ -373,25 +322,10 @@ gid - 2 - 3 + 3 + 4 GTK_FILL - - - - - - True - True - A unique ID to identify the event - - - - 1 - 4 - 2 - 3 - + @@ -405,7 +339,111 @@ 3 4 - + + + + + + True + True + True + none + + + + Private + + + + + True + False + gtk-dialog-authentication + + + Privacy + + + + + + + 4 + 5 + 1 + 2 + + + + + + + True + False + 6 + + + 75 + True + True + A unique ID to identify the event + + 6 + + + False + True + 0 + + + + + True + False + 0 + Tags: + + + False + True + 1 + + + + + True + False + 0 + 0.4699999988079071 + + + True + True + 2 + + + + + True + True + True + 1 + True + right + + + False + False + 3 + + + + + 1 + 5 + 3 + 4 + GTK_FILL diff --git a/gramps/gui/glade/editplace.glade b/gramps/gui/glade/editplace.glade index eb347a985..228bfb77c 100644 --- a/gramps/gui/glade/editplace.glade +++ b/gramps/gui/glade/editplace.glade @@ -16,12 +16,10 @@ gtk-cancel - False True True True True - False True @@ -33,13 +31,11 @@ gtk-ok - False True True True True True - False True @@ -51,12 +47,10 @@ gtk-help - False True True True True - False True @@ -83,12 +77,9 @@ False 12 3 - 4 + 5 6 4 - - - True @@ -149,7 +140,7 @@ 1 - 4 + 5 @@ -169,57 +160,6 @@ - - - True - True - A unique ID to identify the place - - - - 1 - 2 - 2 - 3 - - - - - - False - True - True - True - False - none - - - - Private - - - - - True - False - gtk-dialog-authentication - - - Privacy - - - - - - - 2 - 3 - 2 - 3 - - - - True @@ -254,6 +194,110 @@ You can set these values via the Geography View by searching the place, or via a + + + True + False + 6 + + + 75 + True + True + A unique ID to identify the place + + 6 + + + False + True + 0 + + + + + True + False + 0 + Tags: + + + False + True + 1 + + + + + True + False + 0 + + + True + True + 2 + + + + + 1 + 4 + 2 + 3 + GTK_FILL + + + + + True + True + True + none + + + + Private + + + + + True + False + gtk-dialog-authentication + + + Privacy + + + + + + + 4 + 5 + 1 + 2 + + + + + + + True + True + True + True + + + 4 + 5 + 2 + 3 + + + + False diff --git a/gramps/gui/glade/editrepository.glade b/gramps/gui/glade/editrepository.glade index add6e8b26..23c191176 100644 --- a/gramps/gui/glade/editrepository.glade +++ b/gramps/gui/glade/editrepository.glade @@ -17,7 +17,6 @@ gtk-cancel - False True True True @@ -25,7 +24,6 @@ True Abandon changes and close window Abandon changes and close window - False True @@ -37,7 +35,6 @@ gtk-ok - False True True True @@ -46,7 +43,6 @@ True Accept changes and close window Accept changes and close window - False True @@ -58,12 +54,10 @@ gtk-help - False True True True True - False True @@ -89,7 +83,7 @@ True False 12 - 2 + 3 2 4 4 @@ -97,7 +91,7 @@ True False - 1 + 0 _Name: True center @@ -192,14 +186,12 @@ - False True True True True Indicates if the record is private Indicates if the record is private - False none @@ -236,6 +228,59 @@ GTK_FILL + + + True + False + 0 + Tags: + right + + + 2 + 3 + GTK_FILL + + + + + + True + False + + + True + False + 0 + + + True + True + 0 + + + + + True + True + True + True + + + False + True + 1 + + + + + 1 + 2 + 2 + 3 + GTK_FILL + + False diff --git a/gramps/gui/glade/editsource.glade b/gramps/gui/glade/editsource.glade index 5f7301128..94ee1fa76 100644 --- a/gramps/gui/glade/editsource.glade +++ b/gramps/gui/glade/editsource.glade @@ -18,13 +18,11 @@ gtk-cancel - False True True True False Abandon changes and close window - False True @@ -37,14 +35,12 @@ gtk-ok - False True True True True False Accept changes and close window - False True @@ -57,12 +53,10 @@ gtk-help - False True True True False - False True @@ -90,7 +84,7 @@ False 12 5 - 2 + 3 4 4 @@ -134,7 +128,7 @@ 1 - 2 + 3 @@ -146,7 +140,7 @@
1 - 2 + 3 1 2 @@ -163,8 +157,8 @@ pubinfo - 4 - 5 + 2 + 3 GTK_FILL @@ -177,9 +171,9 @@ 1 - 2 - 4 - 5 + 3 + 2 + 3
@@ -214,6 +208,62 @@
+ + + True + False + 12 + + + 75 + True + True + A unique ID to identify the source + + 6 + + + False + True + 0 + + + + + True + False + 0 + Tags: + + + False + True + 1 + + + + + True + False + 0 + 2 + + + True + True + 2 + + + + + 1 + 2 + 4 + 5 + GTK_FILL + GTK_FILL + + True @@ -224,72 +274,63 @@ gid - 2 - 3 + 4 + 5 GTK_FILL + GTK_FILL + + + + + True + True + True + True + Indicates if the record is private + Indicates if the record is private + none + + + + Private + + + + + True + False + gtk-dialog-authentication + + + Privacy + + + + + + + 2 + 3 + 3 + 4 + - + True - False - 12 - - - True - True - A unique ID to identify the source - - - - True - True - 0 - - - - - False - True - True - False - Indicates if the record is private - False - none - - - - Private - - - - - True - False - gtk-dialog-authentication - - - Privacy - - - - - - - False - False - 1 - - + True + True + True - 1 - 2 - 2 - 3 - GTK_FILL - GTK_FILL + 2 + 3 + 4 + 5 + + diff --git a/gramps/gui/views/listview.py b/gramps/gui/views/listview.py index 9f7227798..68915c8d5 100644 --- a/gramps/gui/views/listview.py +++ b/gramps/gui/views/listview.py @@ -288,11 +288,22 @@ class ListView(NavigationView): renderer.set_property('foreground', fg_color) def set_active(self): + """ + Called when the page is displayed. + """ NavigationView.set_active(self) + self.uistate.viewmanager.tags.tag_enable() self.uistate.show_filter_results(self.dbstate, self.model.displayed(), self.model.total()) + def set_inactive(self): + """ + Called when the page is no longer displayed. + """ + NavigationView.set_inactive(self) + self.uistate.viewmanager.tags.tag_disable() + def __build_tree(self): profile(self._build_tree) @@ -660,7 +671,8 @@ class ListView(NavigationView): """ for sig in self.signal_map: self.callman.add_db_signal(sig, self.signal_map[sig]) - + self.callman.add_db_signal('tag-update', self.tag_updated) + def change_db(self, db): """ Called when the database is changed. diff --git a/gramps/gui/views/tags.py b/gramps/gui/views/tags.py index 6b0fd1374..d1dec6fa7 100644 --- a/gramps/gui/views/tags.py +++ b/gramps/gui/views/tags.py @@ -266,7 +266,7 @@ class Tags(DbGUIElement): # Make the dialog modal so that the user can't start another # database transaction while the one setting tags is still running. pmon = progressdlg.ProgressMonitor(progressdlg.GtkProgressDialog, - ("", self.uistate.window, Gtk.DialogFlags.MODAL), popup_time=2) + ("", self.uistate.window, Gtk.DialogFlags.MODAL), popup_time=2) status = progressdlg.LongOpStatus(msg=_("Adding Tags"), total_steps=len(selected), interval=len(selected)//20) @@ -492,6 +492,8 @@ class OrganizeTagsDialog(object): self.db.commit_place), 'Source': (self.db.get_source_from_handle, self.db.commit_source), + 'Citation': (self.db.get_citation_from_handle, + self.db.commit_citation), 'Repository': (self.db.get_repository_from_handle, self.db.commit_repository), 'MediaObject': (self.db.get_object_from_handle, diff --git a/gramps/gui/views/treemodels/citationbasemodel.py b/gramps/gui/views/treemodels/citationbasemodel.py index abbf7a0fe..37c5e8d99 100644 --- a/gramps/gui/views/treemodels/citationbasemodel.py +++ b/gramps/gui/views/treemodels/citationbasemodel.py @@ -33,6 +33,7 @@ import cgi import logging log = logging.getLogger(".") LOG = logging.getLogger(".citation") +import locale #------------------------------------------------------------------------- # @@ -59,7 +60,8 @@ COLUMN_PAGE = 3 COLUMN_CONFIDENCE = 4 COLUMN_SOURCE = 5 COLUMN_CHANGE = 9 -COLUMN_PRIV = 10 +COLUMN_TAGS = 10 +COLUMN_PRIV = 11 # Data for the Source object COLUMN2_HANDLE = 0 @@ -69,7 +71,8 @@ COLUMN2_AUTHOR = 3 COLUMN2_PUBINFO = 4 COLUMN2_ABBREV = 7 COLUMN2_CHANGE = 8 -COLUMN2_PRIV = 11 +COLUMN2_TAGS = 11 +COLUMN2_PRIV = 12 INVALID_DATE_FORMAT = config.get('preferences.invalid-date-format') @@ -122,6 +125,28 @@ class CitationBaseModel(object): # There is a problem returning None here. return '' + def citation_tags(self, data): + """ + Return the sorted list of tags. + """ + tag_list = list(map(self.get_tag_name, data[COLUMN_TAGS])) + return ', '.join(sorted(tag_list, key=locale.strxfrm)) + + def citation_tag_color(self, data): + """ + Return the tag color. + """ + tag_color = "#000000000000" + tag_priority = None + for handle in data[COLUMN_TAGS]: + tag = self.db.get_tag_from_handle(handle) + if tag: + this_priority = tag.get_priority() + if tag_priority is None or this_priority < tag_priority: + tag_color = tag.get_color() + tag_priority = this_priority + return tag_color + def citation_change(self, data): return format_time(data[COLUMN_CHANGE]) @@ -183,6 +208,15 @@ class CitationBaseModel(object): except: return '' + def citation_src_tags(self, data): + source_handle = data[COLUMN_SOURCE] + try: + source = self.db.get_source_from_handle(source_handle) + tag_list = list(map(self.get_tag_name, source.get_tag_list())) + return ', '.join(sorted(tag_list, key=locale.strxfrm)) + except: + return '' + def citation_src_chan(self, data): source_handle = data[COLUMN_SOURCE] try: @@ -215,6 +249,28 @@ class CitationBaseModel(object): # There is a problem returning None here. return '' + def source_src_tags(self, data): + """ + Return the sorted list of tags. + """ + tag_list = list(map(self.get_tag_name, data[COLUMN2_TAGS])) + return ', '.join(sorted(tag_list, key=locale.strxfrm)) + + def source_src_tag_color(self, data): + """ + Return the tag color. + """ + tag_color = "#000000000000" + tag_priority = None + for handle in data[COLUMN2_TAGS]: + tag = self.db.get_tag_from_handle(handle) + if tag: + this_priority = tag.get_priority() + if tag_priority is None or this_priority < tag_priority: + tag_color = tag.get_color() + tag_priority = this_priority + return tag_color + def source_src_chan(self, data): return format_time(data[COLUMN2_CHANGE]) @@ -224,3 +280,9 @@ class CitationBaseModel(object): def dummy_sort_key(self, data): # dummy sort key for columns that don't have data return None + + def get_tag_name(self, tag_handle): + """ + Return the tag name from the given tag handle. + """ + return self.db.get_tag_from_handle(tag_handle).get_name() diff --git a/gramps/gui/views/treemodels/citationlistmodel.py b/gramps/gui/views/treemodels/citationlistmodel.py index f02359308..808096dbc 100644 --- a/gramps/gui/views/treemodels/citationlistmodel.py +++ b/gramps/gui/views/treemodels/citationlistmodel.py @@ -67,6 +67,7 @@ class CitationListModel(CitationBaseModel, FlatBaseModel): self.citation_date, self.citation_confidence, self.citation_private, + self.citation_tags, self.citation_change, self.citation_src_title, self.citation_src_id, @@ -75,6 +76,7 @@ class CitationListModel(CitationBaseModel, FlatBaseModel): self.citation_src_pinfo, self.citation_src_private, self.citation_src_chan, + self.citation_tag_color ] self.smap = [ self.citation_page, @@ -82,6 +84,7 @@ class CitationListModel(CitationBaseModel, FlatBaseModel): self.citation_sort_date, self.citation_confidence, self.citation_private, + self.citation_tags, self.citation_sort_change, self.citation_src_title, self.citation_src_id, @@ -90,6 +93,7 @@ class CitationListModel(CitationBaseModel, FlatBaseModel): self.citation_src_pinfo, self.citation_src_private, self.citation_src_chan, + self.citation_tag_color ] FlatBaseModel.__init__(self, db, scol, order, search=search, skip=skip, sort_map=sort_map) @@ -105,5 +109,11 @@ class CitationListModel(CitationBaseModel, FlatBaseModel): self.smap = None FlatBaseModel.destroy(self) + def color_column(self): + """ + Return the color column. + """ + return 14 + def do_get_n_columns(self): return len(self.fmap)+1 diff --git a/gramps/gui/views/treemodels/citationtreemodel.py b/gramps/gui/views/treemodels/citationtreemodel.py index 0e504fdc0..3a69abf37 100644 --- a/gramps/gui/views/treemodels/citationtreemodel.py +++ b/gramps/gui/views/treemodels/citationtreemodel.py @@ -80,10 +80,12 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel): None, # COL_DATE (not for Source) None, # COL_CONFIDENCE (not for Source) self.source_src_private, # COL_PRIV (both Source & Citation) + self.source_src_tags, # COL_TAGS (both Source & Citation) self.source_src_chan, # COL_CHAN (both Source & Citation) self.source_src_auth, # COL_SRC_AUTH (Source only) self.source_src_abbr, # COL_SRC_ABBR (Source only) self.source_src_pinfo, # COL_SRC_PINFO (Source only) + self.source_src_tag_color ] self.smap = [ self.source_src_title, @@ -91,10 +93,12 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel): self.dummy_sort_key, self.dummy_sort_key, self.source_src_private, + self.source_src_tags, self.source_sort2_change, self.source_src_auth, self.source_src_abbr, self.source_src_pinfo, + self.source_src_tag_color ] TreeBaseModel.__init__(self, self.db, scol=scol, order=order, @@ -133,10 +137,12 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel): self.citation_date, self.citation_confidence, self.citation_private, + self.citation_tags, self.citation_change, None, None, None, + self.citation_tag_color ] self.smap2 = [ self.citation_page, @@ -144,12 +150,20 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel): self.citation_sort_date, self.citation_confidence, self.citation_private, + self.citation_tags, self.citation_sort_change, self.dummy_sort_key, self.dummy_sort_key, self.dummy_sort_key, + self.citation_tag_color ] + def color_column(self): + """ + Return the color column. + """ + return 10 + def get_tree_levels(self): """ Return the headings of the levels in the hierarchy. diff --git a/gramps/gui/views/treemodels/eventmodel.py b/gramps/gui/views/treemodels/eventmodel.py index c35332a31..5218dc144 100644 --- a/gramps/gui/views/treemodels/eventmodel.py +++ b/gramps/gui/views/treemodels/eventmodel.py @@ -27,6 +27,7 @@ import cgi import logging log = logging.getLogger(".") +import locale #------------------------------------------------------------------------- # @@ -59,7 +60,8 @@ COLUMN_DATE = 3 COLUMN_DESCRIPTION = 4 COLUMN_PLACE = 5 COLUMN_CHANGE = 10 -COLUMN_PRIV = 11 +COLUMN_TAGS = 11 +COLUMN_PRIV = 12 INVALID_DATE_FORMAT = config.get('preferences.invalid-date-format') @@ -82,8 +84,10 @@ class EventModel(FlatBaseModel): self.column_date, self.column_place, self.column_private, + self.column_tags, self.column_change, self.column_participant, + self.column_tag_color ] self.smap = [ self.column_description, @@ -92,8 +96,10 @@ class EventModel(FlatBaseModel): self.sort_date, self.column_place, self.column_private, + self.column_tags, self.sort_change, self.column_participant, + self.column_tag_color ] FlatBaseModel.__init__(self, db, scol, order, search=search, skip=skip, sort_map=sort_map) @@ -109,6 +115,12 @@ class EventModel(FlatBaseModel): self.smap = None FlatBaseModel.destroy(self) + def color_column(self): + """ + Return the color column. + """ + return 9 + def do_get_n_columns(self): return len(self.fmap)+1 @@ -167,3 +179,31 @@ class EventModel(FlatBaseModel): def column_change(self,data): return format_time(data[COLUMN_CHANGE]) + + def get_tag_name(self, tag_handle): + """ + Return the tag name from the given tag handle. + """ + return self.db.get_tag_from_handle(tag_handle).get_name() + + def column_tag_color(self, data): + """ + Return the tag color. + """ + tag_color = "#000000000000" + tag_priority = None + for handle in data[COLUMN_TAGS]: + tag = self.db.get_tag_from_handle(handle) + if tag: + this_priority = tag.get_priority() + if tag_priority is None or this_priority < tag_priority: + tag_color = tag.get_color() + tag_priority = this_priority + return tag_color + + def column_tags(self, data): + """ + Return the sorted list of tags. + """ + tag_list = list(map(self.get_tag_name, data[COLUMN_TAGS])) + return ', '.join(sorted(tag_list, key=locale.strxfrm)) diff --git a/gramps/gui/views/treemodels/placemodel.py b/gramps/gui/views/treemodels/placemodel.py index ce503d146..2928ea846 100644 --- a/gramps/gui/views/treemodels/placemodel.py +++ b/gramps/gui/views/treemodels/placemodel.py @@ -33,6 +33,7 @@ Place Model. import cgi import logging _LOG = logging.getLogger(".gui.views.treemodels.placemodel") +import locale #------------------------------------------------------------------------- # @@ -94,8 +95,10 @@ class PlaceBaseModel(object): self.column_latitude, self.column_longitude, self.column_private, + self.column_tags, self.column_change, self.column_place_name, + self.column_tag_color ] self.smap = [ self.column_name, @@ -111,8 +114,10 @@ class PlaceBaseModel(object): self.sort_latitude, self.sort_longitude, self.column_private, + self.column_tags, self.sort_change, self.column_place_name, + self.column_tag_color ] def destroy(self): @@ -125,6 +130,12 @@ class PlaceBaseModel(object): self.fmap = None self.smap = None + def color_column(self): + """ + Return the color column. + """ + return 16 + def do_get_n_columns(self): return len(self.fmap)+1 @@ -215,7 +226,7 @@ class PlaceBaseModel(object): return '' def column_private(self, data): - if data[12]: + if data[13]: return 'gramps-lock' else: # There is a problem returning None here. @@ -227,6 +238,34 @@ class PlaceBaseModel(object): def column_change(self, data): return format_time(data[11]) + def get_tag_name(self, tag_handle): + """ + Return the tag name from the given tag handle. + """ + return self.db.get_tag_from_handle(tag_handle).get_name() + + def column_tag_color(self, data): + """ + Return the tag color. + """ + tag_color = "#000000000000" + tag_priority = None + for handle in data[12]: + tag = self.db.get_tag_from_handle(handle) + if tag: + this_priority = tag.get_priority() + if tag_priority is None or this_priority < tag_priority: + tag_color = tag.get_color() + tag_priority = this_priority + return tag_color + + def column_tags(self, data): + """ + Return the sorted list of tags. + """ + tag_list = list(map(self.get_tag_name, data[12])) + return ', '.join(sorted(tag_list, key=locale.strxfrm)) + #------------------------------------------------------------------------- # # PlaceListModel diff --git a/gramps/gui/views/treemodels/repomodel.py b/gramps/gui/views/treemodels/repomodel.py index 975189711..dd37dbf87 100644 --- a/gramps/gui/views/treemodels/repomodel.py +++ b/gramps/gui/views/treemodels/repomodel.py @@ -26,6 +26,7 @@ #------------------------------------------------------------------------- import logging log = logging.getLogger(".") +import locale #------------------------------------------------------------------------- # @@ -70,7 +71,9 @@ class RepositoryModel(FlatBaseModel): self.column_email, self.column_search_url, self.column_private, + self.column_tags, self.column_change, + self.column_tag_color ] self.smap = [ @@ -87,7 +90,9 @@ class RepositoryModel(FlatBaseModel): self.column_email, self.column_search_url, self.column_private, + self.column_tags, self.sort_change, + self.column_tag_color ] FlatBaseModel.__init__(self, db, scol, order, search=search, skip=skip, @@ -105,6 +110,12 @@ class RepositoryModel(FlatBaseModel): self.smap = None FlatBaseModel.destroy(self) + def color_column(self): + """ + Return the color column. + """ + return 15 + def do_get_n_columns(self): return len(self.fmap)+1 @@ -215,7 +226,7 @@ class RepositoryModel(FlatBaseModel): return "" def column_private(self, data): - if data[8]: + if data[9]: return 'gramps-lock' else: # There is a problem returning None here. @@ -226,3 +237,31 @@ class RepositoryModel(FlatBaseModel): def column_change(self,data): return format_time(data[7]) + + def get_tag_name(self, tag_handle): + """ + Return the tag name from the given tag handle. + """ + return self.db.get_tag_from_handle(tag_handle).get_name() + + def column_tag_color(self, data): + """ + Return the tag color. + """ + tag_color = "#000000000000" + tag_priority = None + for handle in data[8]: + tag = self.db.get_tag_from_handle(handle) + if tag: + this_priority = tag.get_priority() + if tag_priority is None or this_priority < tag_priority: + tag_color = tag.get_color() + tag_priority = this_priority + return tag_color + + def column_tags(self, data): + """ + Return the sorted list of tags. + """ + tag_list = list(map(self.get_tag_name, data[8])) + return ', '.join(sorted(tag_list, key=locale.strxfrm)) diff --git a/gramps/gui/views/treemodels/sourcemodel.py b/gramps/gui/views/treemodels/sourcemodel.py index 25a5ace49..52d34e980 100644 --- a/gramps/gui/views/treemodels/sourcemodel.py +++ b/gramps/gui/views/treemodels/sourcemodel.py @@ -26,6 +26,7 @@ #------------------------------------------------------------------------- import logging log = logging.getLogger(".") +import locale #------------------------------------------------------------------------- # @@ -61,7 +62,9 @@ class SourceModel(FlatBaseModel): self.column_abbrev, self.column_pubinfo, self.column_private, + self.column_tags, self.column_change, + self.column_tag_color ] self.smap = [ self.column_title, @@ -70,7 +73,9 @@ class SourceModel(FlatBaseModel): self.column_abbrev, self.column_pubinfo, self.column_private, + self.column_tags, self.sort_change, + self.column_tag_color ] FlatBaseModel.__init__(self, db, scol, order, search=search, skip=skip, sort_map=sort_map) @@ -86,6 +91,12 @@ class SourceModel(FlatBaseModel): self.smap = None FlatBaseModel.destroy(self) + def color_column(self): + """ + Return the color column. + """ + return 8 + def do_get_n_columns(self): return len(self.fmap)+1 @@ -105,7 +116,7 @@ class SourceModel(FlatBaseModel): return cuni(data[4]) def column_private(self, data): - if data[11]: + if data[12]: return 'gramps-lock' else: # There is a problem returning None here. @@ -116,3 +127,31 @@ class SourceModel(FlatBaseModel): def sort_change(self,data): return "%012x" % data[8] + + def get_tag_name(self, tag_handle): + """ + Return the tag name from the given tag handle. + """ + return self.db.get_tag_from_handle(tag_handle).get_name() + + def column_tag_color(self, data): + """ + Return the tag color. + """ + tag_color = "#000000000000" + tag_priority = None + for handle in data[11]: + tag = self.db.get_tag_from_handle(handle) + if tag: + this_priority = tag.get_priority() + if tag_priority is None or this_priority < tag_priority: + tag_color = tag.get_color() + tag_priority = this_priority + return tag_color + + def column_tags(self, data): + """ + Return the sorted list of tags. + """ + tag_list = list(map(self.get_tag_name, data[11])) + return ', '.join(sorted(tag_list, key=locale.strxfrm)) diff --git a/gramps/plugins/export/exportxml.py b/gramps/plugins/export/exportxml.py index 69a05b764..c97c031e5 100644 --- a/gramps/plugins/export/exportxml.py +++ b/gramps/plugins/export/exportxml.py @@ -584,6 +584,10 @@ class GrampsXmlWriter(UpdateCallback): self.write_media_list(citation.get_media_list(), index+1) self.write_data_map(citation.get_data_map()) self.write_ref("sourceref", citation.get_reference_handle(), index+1) + + for tag_handle in citation.get_tag_list(): + self.write_ref("tagref", tag_handle, index+1) + self.g.write("%s\n" % sp) def write_source(self,source,index=1): @@ -597,6 +601,10 @@ class GrampsXmlWriter(UpdateCallback): self.write_media_list(source.get_media_list(),index+1) self.write_data_map(source.get_data_map()) self.write_reporef_list(source.get_reporef_list(),index+1) + + for tag_handle in source.get_tag_list(): + self.write_ref("tagref", tag_handle, index+1) + self.g.write("%s\n" % sp) def write_repository(self,repo,index=1): @@ -612,6 +620,10 @@ class GrampsXmlWriter(UpdateCallback): # url list self.write_url_list(repo.get_url_list(),index+1) self.write_note_list(repo.get_note_list(),index+1) + + for tag_handle in repo.get_tag_list(): + self.write_ref("tagref", tag_handle, index+1) + self.g.write("%s\n" % sp) def write_address_list(self, obj,index=1): @@ -722,6 +734,10 @@ class GrampsXmlWriter(UpdateCallback): for citation_handle in event.get_citation_list(): self.write_ref("citationref", citation_handle, index+1) self.write_media_list(event.get_media_list(),index+1) + + for tag_handle in event.get_tag_list(): + self.write_ref("tagref", tag_handle, index+1) + self.g.write("%s\n" % sp) def dump_ordinance(self, ord,index=1): @@ -1187,6 +1203,10 @@ class GrampsXmlWriter(UpdateCallback): self.write_note_list(place.get_note_list(), index+1) for citation_handle in place.get_citation_list(): self.write_ref("citationref", citation_handle, index+1) + + for tag_handle in place.get_tag_list(): + self.write_ref("tagref", tag_handle, index+1) + self.g.write("%s\n" % (" "*index)) def write_object(self, obj, index=1): diff --git a/gramps/plugins/importer/importxml.py b/gramps/plugins/importer/importxml.py index 3860485c6..102717872 100644 --- a/gramps/plugins/importer/importxml.py +++ b/gramps/plugins/importer/importxml.py @@ -1755,7 +1755,22 @@ class GrampsParser(UpdateCallback): if self.note: self.note.add_tag(handle) - + + if self.event: + self.event.add_tag(handle) + + if self.placeobj: + self.placeobj.add_tag(handle) + + if self.repo: + self.repo.add_tag(handle) + + if self.source: + self.source.add_tag(handle) + + if self.citation: + self.citation.add_tag(handle) + def start_range(self, attrs): self.note_tags[-1].ranges.append((int(attrs['start']), int(attrs['end']))) diff --git a/gramps/plugins/lib/libgrampsxml.py b/gramps/plugins/lib/libgrampsxml.py index 728474c9e..dcebedf69 100644 --- a/gramps/plugins/lib/libgrampsxml.py +++ b/gramps/plugins/lib/libgrampsxml.py @@ -35,5 +35,5 @@ # Public Constants # #------------------------------------------------------------------------ -GRAMPS_XML_VERSION = "1.5.0" +GRAMPS_XML_VERSION = "1.6.0" diff --git a/gramps/plugins/lib/libpersonview.py b/gramps/plugins/lib/libpersonview.py index 21f603467..03c89756f 100644 --- a/gramps/plugins/lib/libpersonview.py +++ b/gramps/plugins/lib/libpersonview.py @@ -129,7 +129,6 @@ class BasePersonView(ListView): 'person-delete' : self.row_delete, 'person-rebuild' : self.object_build, 'person-groupname-rebuild' : self.object_build, - 'tag-update' : self.tag_updated, 'no-database': self.no_database, } @@ -375,20 +374,6 @@ class BasePersonView(ListView): self.all_action.set_visible(False) self.edit_action.set_visible(False) - def set_active(self): - """ - Called when the page is displayed. - """ - ListView.set_active(self) - self.uistate.viewmanager.tags.tag_enable() - - def set_inactive(self): - """ - Called when the page is no longer displayed. - """ - ListView.set_inactive(self) - self.uistate.viewmanager.tags.tag_disable() - def merge(self, obj): """ Merge the selected people. diff --git a/gramps/plugins/lib/libplaceview.py b/gramps/plugins/lib/libplaceview.py index 37c3a58ca..7e1c86ead 100644 --- a/gramps/plugins/lib/libplaceview.py +++ b/gramps/plugins/lib/libplaceview.py @@ -90,7 +90,8 @@ class PlaceBaseView(ListView): COL_LAT = 10 COL_LON = 11 COL_PRIV = 12 - COL_CHAN = 13 + COL_TAGS = 13 + COL_CHAN = 14 # column definitions COLUMNS = [ (_('Place Name'), MARKUP, None), @@ -106,6 +107,7 @@ class PlaceBaseView(ListView): (_('Latitude'), TEXT, None), (_('Longitude'), TEXT, None), (_('Private'), ICON, 'gramps-lock'), + (_('Tags'), TEXT, None), (_('Last Changed'), TEXT, None), ] # default setting with visible columns, order of the col, and their size @@ -114,9 +116,10 @@ class PlaceBaseView(ListView): COL_CITY, COL_COUNTY, COL_STATE]), ('columns.rank', [COL_NAME, COL_ID, COL_STREET, COL_LOCALITY, COL_CITY, COL_COUNTY, COL_STATE, COL_COUNTRY, COL_ZIP, - COL_PARISH, COL_LAT, COL_LON, COL_PRIV, COL_CHAN]), + COL_PARISH, COL_LAT, COL_LON, COL_PRIV, COL_TAGS, + COL_CHAN]), ('columns.size', [250, 75, 150, 150, 150, 150, 100, 100, 100, - 100, 150, 150, 40, 100]) + 100, 150, 150, 40, 100, 100]) ) ADD_MSG = _("Add a new place") EDIT_MSG = _("Edit the selected place") @@ -429,6 +432,26 @@ class PlaceBaseView(ListView): else: return None + def tag_updated(self, handle_list): + """ + Update tagged rows when a tag color changes. + """ + all_links = set([]) + for tag_handle in handle_list: + links = set([link[1] for link in + self.dbstate.db.find_backlink_handles(tag_handle, + include_classes='Place')]) + all_links = all_links.union(links) + self.row_update(list(all_links)) + + def add_tag(self, transaction, place_handle, tag_handle): + """ + Add the given tag to the given place. + """ + place = self.dbstate.db.get_place_from_handle(place_handle) + place.add_tag(tag_handle) + self.dbstate.db.commit_place(place, transaction) + def get_default_gramplets(self): """ Define the default gramplets for the sidebar and bottombar. diff --git a/gramps/plugins/view/citationlistview.py b/gramps/plugins/view/citationlistview.py index d9a9157c7..807a85172 100644 --- a/gramps/plugins/view/citationlistview.py +++ b/gramps/plugins/view/citationlistview.py @@ -85,15 +85,16 @@ class CitationListView(ListView): COL_ID = 1 COL_DATE = 2 COL_CONFIDENCE = 3 - COL_PRIV = 4 - COL_CHAN = 5 - COL_SRC_TITLE = 6 - COL_SRC_ID = 7 - COL_SRC_AUTH = 8 - COL_SRC_ABBR = 9 - COL_SRC_PINFO = 10 - COL_SRC_PRIV = 11 - COL_SRC_CHAN = 12 + COL_PRIV = 4 + COL_TAGS = 5 + COL_CHAN = 6 + COL_SRC_TITLE = 7 + COL_SRC_ID = 8 + COL_SRC_AUTH = 9 + COL_SRC_ABBR = 10 + COL_SRC_PINFO = 11 + COL_SRC_PRIV = 12 + COL_SRC_CHAN = 13 # column definitions COLUMNS = [ (_('Volume/Page'), TEXT, None), @@ -101,6 +102,7 @@ class CitationListView(ListView): (_('Date'), MARKUP, None), (_('Confidence'), TEXT, None), (_('Private'), ICON, 'gramps-lock'), + (_('Tags'), TEXT, None), (_('Last Changed'), TEXT, None), (_('Source: Title'), TEXT, None), (_('Source: ID'), TEXT, None), @@ -115,11 +117,11 @@ class CitationListView(ListView): ('columns.visible', [COL_TITLE_PAGE, COL_ID, COL_DATE, COL_CONFIDENCE]), ('columns.rank', [COL_TITLE_PAGE, COL_ID, COL_DATE, COL_CONFIDENCE, - COL_PRIV, COL_CHAN, COL_SRC_TITLE, COL_SRC_ID, - COL_SRC_AUTH, COL_SRC_ABBR, COL_SRC_PINFO, + COL_PRIV, COL_TAGS, COL_CHAN, COL_SRC_TITLE, + COL_SRC_ID, COL_SRC_AUTH, COL_SRC_ABBR, COL_SRC_PINFO, COL_SRC_PRIV, COL_SRC_CHAN]), - ('columns.size', [200, 75, 100, 100, 40, 100, 200, 75, 75, 100, 150, - 40, 100]) + ('columns.size', [200, 75, 100, 100, 40, 100, 100, 200, 75, 75, 100, + 150, 40, 100]) ) ADD_MSG = _("Add a new citation and a new source") ADD_SOURCE_MSG = _("Add a new source") @@ -335,6 +337,26 @@ class CitationListView(ListView): else: return None + def tag_updated(self, handle_list): + """ + Update tagged rows when a tag color changes. + """ + all_links = set([]) + for tag_handle in handle_list: + links = set([link[1] for link in + self.dbstate.db.find_backlink_handles(tag_handle, + include_classes='Citation')]) + all_links = all_links.union(links) + self.row_update(list(all_links)) + + def add_tag(self, transaction, citation_handle, tag_handle): + """ + Add the given tag to the given citation. + """ + citation = self.dbstate.db.get_citation_from_handle(citation_handle) + citation.add_tag(tag_handle) + self.dbstate.db.commit_citation(citation, transaction) + def get_default_gramplets(self): """ Define the default gramplets for the sidebar and bottombar. diff --git a/gramps/plugins/view/citationtreeview.py b/gramps/plugins/view/citationtreeview.py index 45940c63e..941fc1a5d 100644 --- a/gramps/plugins/view/citationtreeview.py +++ b/gramps/plugins/view/citationtreeview.py @@ -85,10 +85,11 @@ class CitationTreeView(ListView): COL_DATE = 2 COL_CONFIDENCE = 3 COL_PRIV = 4 - COL_CHAN = 5 - COL_SRC_AUTH = 6 - COL_SRC_ABBR = 7 - COL_SRC_PINFO = 8 + COL_TAGS = 5 + COL_CHAN = 6 + COL_SRC_AUTH = 7 + COL_SRC_ABBR = 8 + COL_SRC_PINFO = 9 # column definitions COLUMNS = [ (_('Title or Page'), TEXT, None), @@ -96,6 +97,7 @@ class CitationTreeView(ListView): (_('Date'), MARKUP, None), (_('Confidence'), TEXT, None), (_('Private'), ICON, 'gramps-lock'), + (_('Tags'), TEXT, None), (_('Last Changed'), TEXT, None), (_('Source: Author'), TEXT, None), (_('Source: Abbreviation'), TEXT, None), @@ -114,9 +116,9 @@ class CitationTreeView(ListView): ('columns.visible', [COL_TITLE_PAGE, COL_ID, COL_SRC_AUTH, COL_SRC_PINFO]), ('columns.rank', [COL_TITLE_PAGE, COL_ID, COL_DATE, COL_CONFIDENCE, - COL_PRIV, COL_CHAN, COL_SRC_AUTH, + COL_PRIV, COL_TAGS, COL_CHAN, COL_SRC_AUTH, COL_SRC_ABBR, COL_SRC_PINFO]), - ('columns.size', [200, 75, 100, 75, 40, 100, 150, 100, 150]) + ('columns.size', [200, 75, 100, 75, 40, 100, 100, 150, 100, 150]) ) ADD_MSG = _("Add a new citation and a new source") ADD_SOURCE_MSG = _("Add a new source") @@ -550,6 +552,26 @@ class CitationTreeView(ListView): else: return None + def tag_updated(self, handle_list): + """ + Update tagged rows when a tag color changes. + """ + all_links = set([]) + for tag_handle in handle_list: + links = set([link[1] for link in + self.dbstate.db.find_backlink_handles(tag_handle, + include_classes='Citation')]) + all_links = all_links.union(links) + self.row_update(list(all_links)) + + def add_tag(self, transaction, citation_handle, tag_handle): + """ + Add the given tag to the given citation. + """ + citation = self.dbstate.db.get_citation_from_handle(citation_handle) + citation.add_tag(tag_handle) + self.dbstate.db.commit_citation(citation, transaction) + def get_default_gramplets(self): """ Define the default gramplets for the sidebar and bottombar. diff --git a/gramps/plugins/view/eventview.py b/gramps/plugins/view/eventview.py index b3c9313e2..6ca110513 100644 --- a/gramps/plugins/view/eventview.py +++ b/gramps/plugins/view/eventview.py @@ -76,8 +76,9 @@ class EventView(ListView): COL_DATE = 3 COL_PLACE = 4 COL_PRIV = 5 - COL_CHAN = 6 - COL_PARTIC = 7 + COL_TAGS = 6 + COL_CHAN = 7 + COL_PARTIC = 8 # column definitions COLUMNS = [ (_('Description'), TEXT, None), @@ -86,6 +87,7 @@ class EventView(ListView): (_('Date'), MARKUP, None), (_('Place'), TEXT, None), (_('Private'), ICON, 'gramps-lock'), + (_('Tags'), TEXT, None), (_('Last Changed'), TEXT, None), (_('Main Participants'), TEXT, None), ] @@ -93,8 +95,8 @@ class EventView(ListView): CONFIGSETTINGS = ( ('columns.visible', [COL_DESCR, COL_ID, COL_TYPE, COL_DATE, COL_PLACE]), ('columns.rank', [COL_DESCR, COL_ID, COL_TYPE, COL_PARTIC, COL_DATE, - COL_PLACE, COL_PRIV, COL_CHAN]), - ('columns.size', [200, 75, 100, 230, 150, 200, 40, 100]) + COL_PLACE, COL_PRIV, COL_TAGS, COL_CHAN]), + ('columns.size', [200, 75, 100, 230, 150, 200, 40, 100, 100]) ) ADD_MSG = _("Add a new event") EDIT_MSG = _("Edit the selected event") @@ -267,6 +269,26 @@ class EventView(ListView): else: MergeEvent(self.dbstate, self.uistate, mlist[0], mlist[1]) + def tag_updated(self, handle_list): + """ + Update tagged rows when a tag color changes. + """ + all_links = set([]) + for tag_handle in handle_list: + links = set([link[1] for link in + self.dbstate.db.find_backlink_handles(tag_handle, + include_classes='Event')]) + all_links = all_links.union(links) + self.row_update(list(all_links)) + + def add_tag(self, transaction, event_handle, tag_handle): + """ + Add the given tag to the given event. + """ + event = self.dbstate.db.get_event_from_handle(event_handle) + event.add_tag(tag_handle) + self.dbstate.db.commit_event(event, transaction) + def get_default_gramplets(self): """ Define the default gramplets for the sidebar and bottombar. diff --git a/gramps/plugins/view/familyview.py b/gramps/plugins/view/familyview.py index 89a5102dc..8a9ff9ebc 100644 --- a/gramps/plugins/view/familyview.py +++ b/gramps/plugins/view/familyview.py @@ -110,7 +110,6 @@ class FamilyView(ListView): 'family-update' : self.row_update, 'family-delete' : self.row_delete, 'family-rebuild' : self.object_build, - 'tag-update' : self.tag_updated } ListView.__init__( @@ -213,20 +212,6 @@ class FamilyView(ListView): ]) self._add_action_group(self.all_action) - def set_active(self): - """ - Called when the page is displayed. - """ - ListView.set_active(self) - self.uistate.viewmanager.tags.tag_enable() - - def set_inactive(self): - """ - Called when the page is no longer displayed. - """ - ListView.set_inactive(self) - self.uistate.viewmanager.tags.tag_disable() - def add_bookmark(self, obj): mlist = self.selected_handles() if mlist: diff --git a/gramps/plugins/view/mediaview.py b/gramps/plugins/view/mediaview.py index cc37291c9..89f29c32f 100644 --- a/gramps/plugins/view/mediaview.py +++ b/gramps/plugins/view/mediaview.py @@ -133,7 +133,6 @@ class MediaView(ListView): 'media-update' : self.row_update, 'media-delete' : self.row_delete, 'media-rebuild' : self.object_build, - 'tag-update' : self.tag_updated } ListView.__init__( @@ -232,20 +231,6 @@ class MediaView(ListView): self._add_action('QuickReport', None, _("Quick View"), None, None, None) - def set_active(self): - """ - Called when the page is displayed. - """ - ListView.set_active(self) - self.uistate.viewmanager.tags.tag_enable() - - def set_inactive(self): - """ - Called when the page is no longer displayed. - """ - ListView.set_inactive(self) - self.uistate.viewmanager.tags.tag_disable() - def view_media(self, obj): """ Launch external viewers for the selected objects. diff --git a/gramps/plugins/view/noteview.py b/gramps/plugins/view/noteview.py index 99cb71ab9..4744a6543 100644 --- a/gramps/plugins/view/noteview.py +++ b/gramps/plugins/view/noteview.py @@ -106,7 +106,6 @@ class NoteView(ListView): 'note-update' : self.row_update, 'note-delete' : self.row_delete, 'note-rebuild' : self.object_build, - 'tag-update' : self.tag_updated } ListView.__init__( @@ -203,20 +202,6 @@ class NoteView(ListView): callback=self.filter_editor,) self._add_action('QuickReport', None, _("Quick View"), None, None, None) - def set_active(self): - """ - Called when the page is displayed. - """ - ListView.set_active(self) - self.uistate.viewmanager.tags.tag_enable() - - def set_inactive(self): - """ - Called when the page is no longer displayed. - """ - ListView.set_inactive(self) - self.uistate.viewmanager.tags.tag_disable() - def get_handle_from_gramps_id(self, gid): obj = self.dbstate.db.get_note_from_gramps_id(gid) if obj: diff --git a/gramps/plugins/view/placetreeview.py b/gramps/plugins/view/placetreeview.py index 3f43aacad..08a47fbfb 100644 --- a/gramps/plugins/view/placetreeview.py +++ b/gramps/plugins/view/placetreeview.py @@ -67,8 +67,9 @@ class PlaceTreeView(PlaceBaseView): COL_LAT = 10 COL_LON = 11 COL_PRIV = 12 - COL_CHAN = 13 - COL_NAME = 14 + COL_TAGS = 13 + COL_CHAN = 14 + COL_NAME = 15 # column definitions COLUMNS = [ (_('Place'), MARKUP, None), @@ -84,6 +85,7 @@ class PlaceTreeView(PlaceBaseView): (_('Latitude'), TEXT, None), (_('Longitude'), TEXT, None), (_('Private'), ICON, 'gramps-lock'), + (_('Tags'), TEXT, None), (_('Last Changed'), TEXT, None), (_('Place Name'), TEXT, None), ] @@ -93,10 +95,10 @@ class PlaceTreeView(PlaceBaseView): COL_CITY, COL_COUNTY, COL_STATE]), ('columns.rank', [COL_PLACE, COL_ID, COL_STREET, COL_LOCALITY, COL_CITY, COL_COUNTY, COL_STATE, COL_COUNTRY, COL_ZIP, - COL_PARISH, COL_LAT, COL_LON, COL_PRIV, COL_CHAN, - COL_NAME]), + COL_PARISH, COL_LAT, COL_LON, COL_PRIV, COL_TAGS, + COL_CHAN, COL_NAME]), ('columns.size', [250, 75, 150, 150, 150, 150, 100, 100, 100, - 100, 150, 150, 40, 100, 150]) + 100, 150, 150, 40, 100, 100, 150]) ) def __init__(self, pdata, dbstate, uistate): diff --git a/gramps/plugins/view/repoview.py b/gramps/plugins/view/repoview.py index b970a914b..cd54616d5 100644 --- a/gramps/plugins/view/repoview.py +++ b/gramps/plugins/view/repoview.py @@ -79,7 +79,8 @@ class RepositoryView(ListView): COL_EMAIL = 10 COL_SURL = 11 COL_PRIV = 12 - COL_CHAN = 13 + COL_TAGS = 13 + COL_CHAN = 14 # column definitions COLUMNS = [ @@ -96,6 +97,7 @@ class RepositoryView(ListView): (_('Email'), TEXT, None), (_('Search URL'), TEXT, None), (_('Private'), ICON, 'gramps-lock'), + (_('Tags'), TEXT, None), (_('Last Changed'), TEXT, None), ] # default setting with visible columns, order of the col, and their size @@ -104,9 +106,10 @@ class RepositoryView(ListView): ]), ('columns.rank', [COL_NAME, COL_ID, COL_TYPE, COL_URL, COL_STREET, COL_LOCALITY, COL_CITY, COL_STATE, COL_COUNTRY, - COL_ZIP, COL_EMAIL, COL_SURL, COL_PRIV, COL_CHAN]), + COL_ZIP, COL_EMAIL, COL_SURL, COL_PRIV, COL_TAGS, + COL_CHAN]), ('columns.size', [200, 75, 100, 250, 100, 100, 100, 100, 100, - 100, 100, 100, 40, 100]) + 100, 100, 100, 40, 100, 100]) ) ADD_MSG = _("Add a new repository") EDIT_MSG = _("Edit the selected repository") @@ -257,6 +260,26 @@ class RepositoryView(ListView): else: return None + def tag_updated(self, handle_list): + """ + Update tagged rows when a tag color changes. + """ + all_links = set([]) + for tag_handle in handle_list: + links = set([link[1] for link in + self.dbstate.db.find_backlink_handles(tag_handle, + include_classes='Repository')]) + all_links = all_links.union(links) + self.row_update(list(all_links)) + + def add_tag(self, transaction, repo_handle, tag_handle): + """ + Add the given tag to the given repository. + """ + repo = self.dbstate.db.get_repository_from_handle(repo_handle) + repo.add_tag(tag_handle) + self.dbstate.db.commit_repository(repo, transaction) + def get_default_gramplets(self): """ Define the default gramplets for the sidebar and bottombar. diff --git a/gramps/plugins/view/sourceview.py b/gramps/plugins/view/sourceview.py index e7b781d19..9ec64e09c 100644 --- a/gramps/plugins/view/sourceview.py +++ b/gramps/plugins/view/sourceview.py @@ -76,7 +76,8 @@ class SourceView(ListView): COL_ABBR = 3 COL_PINFO = 4 COL_PRIV = 5 - COL_CHAN = 6 + COL_TAGS = 6 + COL_CHAN = 7 # column definitions COLUMNS = [ @@ -86,14 +87,15 @@ class SourceView(ListView): (_('Abbreviation'), TEXT, None), (_('Publication Information'), TEXT, None), (_('Private'), ICON, 'gramps-lock'), + (_('Tags'), TEXT, None), (_('Last Changed'), TEXT, None), ] # default setting with visible columns, order of the col, and their size CONFIGSETTINGS = ( ('columns.visible', [COL_TITLE, COL_ID, COL_AUTH, COL_PINFO]), ('columns.rank', [COL_TITLE, COL_ID, COL_AUTH, COL_ABBR, COL_PINFO, - COL_PRIV, COL_CHAN]), - ('columns.size', [200, 75, 150, 100, 150, 40, 100]) + COL_PRIV, COL_TAGS, COL_CHAN]), + ('columns.size', [200, 75, 150, 100, 150, 40, 100, 100]) ) ADD_MSG = _("Add a new source") EDIT_MSG = _("Edit the selected source") @@ -241,6 +243,26 @@ class SourceView(ListView): else: return None + def tag_updated(self, handle_list): + """ + Update tagged rows when a tag color changes. + """ + all_links = set([]) + for tag_handle in handle_list: + links = set([link[1] for link in + self.dbstate.db.find_backlink_handles(tag_handle, + include_classes='Source')]) + all_links = all_links.union(links) + self.row_update(list(all_links)) + + def add_tag(self, transaction, source_handle, tag_handle): + """ + Add the given tag to the given source. + """ + source = self.dbstate.db.get_source_from_handle(source_handle) + source.add_tag(tag_handle) + self.dbstate.db.commit_source(source, transaction) + def get_default_gramplets(self): """ Define the default gramplets for the sidebar and bottombar.