1#
2# Gramps - a GTK+/GNOME based genealogy program
3#
4# Copyright (C) 2010  Nick Hall
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19#
20
21"""
22TagBase class for Gramps.
23"""
24
25#-------------------------------------------------------------------------
26#
27# TagBase class
28#
29#-------------------------------------------------------------------------
30class TagBase:
31    """
32    Base class for tag-aware objects.
33    """
34
35    def __init__(self, source=None):
36        """
37        Initialize a TagBase.
38
39        If the source is not None, then object is initialized from values of
40        the source object.
41
42        :param source: Object used to initialize the new object
43        :type source: TagBase
44        """
45        if source:
46            self.tag_list = list(source.tag_list)
47        else:
48            self.tag_list = []
49
50    def serialize(self):
51        """
52        Convert the object to a serialized tuple of data.
53        """
54        return self.tag_list
55
56    def unserialize(self, data):
57        """
58        Convert a serialized tuple of data to an object.
59        """
60        self.tag_list = data
61        return self
62
63    def add_tag(self, tag):
64        """
65        Add the tag to the object's list of tags.
66
67        :param tag: unicode tag to add.
68        :type tag: unicode
69        """
70        if tag not in self.tag_list:
71            self.tag_list.append(tag)
72
73    def remove_tag(self, tag):
74        """
75        Remove the specified tag from the tag list.
76
77        If the tag does not exist in the list, the operation has no effect.
78
79        :param tag: tag to remove from the list.
80        :type tag: unicode
81
82        :returns: True if the tag was removed, False if it was not in the list.
83        :rtype: bool
84        """
85        if tag in self.tag_list:
86            self.tag_list.remove(tag)
87            return True
88        else:
89            return False
90
91    def get_tag_list(self):
92        """
93        Return the list of tags associated with the object.
94
95        :returns: Returns the list of tags.
96        :rtype: list
97        """
98        return self.tag_list
99
100    def set_tag_list(self, tag_list):
101        """
102        Assign the passed list to the objects's list of tags.
103
104        :param tag_list: List of tags to ba associated with the object.
105        :type tag_list: list
106        """
107        self.tag_list = tag_list
108
109    def get_referenced_tag_handles(self):
110        """
111        Return the list of (classname, handle) tuples for all referenced tags.
112
113        This method should be used to get the :class:`~.tag.Tag` portion
114        of the list by objects that store tag lists.
115
116        :returns: List of (classname, handle) tuples for referenced objects.
117        :rtype: list
118        """
119        return [('Tag', handle) for handle in self.tag_list]
120
121    def _merge_tag_list(self, acquisition):
122        """
123        Merge the list of tag from acquisition with our own.
124
125        :param acquisition: The tag list of this object will be merged with
126                            the current tag list.
127        :type acquisition: TagBase
128        """
129        for addendum in acquisition.get_tag_list():
130            self.add_tag(addendum)
131
132    def replace_tag_references(self, old_handle, new_handle):
133        """
134        Replace references to note handles in the list of this object and
135        merge equivalent entries.
136
137        :param old_handle: The note handle to be replaced.
138        :type old_handle: str
139        :param new_handle: The note handle to replace the old one with.
140        :type new_handle: str
141        """
142        refs_list = self.tag_list[:]
143        new_ref = None
144        if new_handle in self.tag_list:
145            new_ref = new_handle
146        n_replace = refs_list.count(old_handle)
147        for ix_replace in range(n_replace):
148            idx = refs_list.index(old_handle)
149            if new_ref:
150                self.tag_list.pop(idx)
151                refs_list.pop(idx)
152            else:
153                self.tag_list[idx] = new_handle
154
155