1#
2# Gramps - a GTK+/GNOME based genealogy program
3#
4# Copyright (C) 2000-2007  Donald N. Allingham
5# Copyright (C) 2010       Nick Hall
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20#
21
22#-------------------------------------------------------------------------
23#
24# python modules
25#
26#-------------------------------------------------------------------------
27import logging
28log = logging.getLogger(".")
29
30#-------------------------------------------------------------------------
31#
32# GNOME/GTK modules
33#
34#-------------------------------------------------------------------------
35from gi.repository import Gtk
36
37#-------------------------------------------------------------------------
38#
39# Gramps modules
40#
41#-------------------------------------------------------------------------
42from gramps.gen.datehandler import displayer, format_time, get_date_valid
43from gramps.gen.display.name import displayer as name_displayer
44from gramps.gen.lib import EventRoleType, FamilyRelType
45from .flatbasemodel import FlatBaseModel
46from gramps.gen.utils.db import get_marriage_or_fallback
47from gramps.gen.config import config
48from gramps.gen.const import GRAMPS_LOCALE as glocale
49
50invalid_date_format = config.get('preferences.invalid-date-format')
51
52#-------------------------------------------------------------------------
53#
54# FamilyModel
55#
56#-------------------------------------------------------------------------
57class FamilyModel(FlatBaseModel):
58
59    def __init__(self, db, uistate, scol=0, order=Gtk.SortType.ASCENDING,
60                 search=None, skip=set(), sort_map=None):
61        self.gen_cursor = db.get_family_cursor
62        self.map = db.get_raw_family_data
63        self.fmap = [
64            self.column_id,
65            self.column_father,
66            self.column_mother,
67            self.column_type,
68            self.column_marriage,
69            self.column_private,
70            self.column_tags,
71            self.column_change,
72            self.column_tag_color,
73            ]
74        self.smap = [
75            self.column_id,
76            self.sort_father,
77            self.sort_mother,
78            self.column_type,
79            self.sort_marriage,
80            self.column_private,
81            self.column_tags,
82            self.sort_change,
83            self.column_tag_color,
84            ]
85        FlatBaseModel.__init__(self, db, uistate, scol, order, search=search,
86                               skip=skip, sort_map=sort_map)
87
88    def destroy(self):
89        """
90        Unset all elements that can prevent garbage collection
91        """
92        self.db = None
93        self.gen_cursor = None
94        self.map = None
95        self.fmap = None
96        self.smap = None
97        FlatBaseModel.destroy(self)
98
99    def color_column(self):
100        """
101        Return the color column.
102        """
103        return 8
104
105    def on_get_n_columns(self):
106        return len(self.fmap)+1
107
108    def column_father(self, data):
109        handle = data[0]
110        cached, value = self.get_cached_value(handle, "FATHER")
111        if not cached:
112            if data[2]:
113                person = self.db.get_person_from_handle(data[2])
114                value = name_displayer.display_name(person.primary_name)
115            else:
116                value = ""
117            self.set_cached_value(handle, "FATHER", value)
118        return value
119
120    def sort_father(self, data):
121        handle = data[0]
122        cached, value = self.get_cached_value(handle, "SORT_FATHER")
123        if not cached:
124            if data[2]:
125                person = self.db.get_person_from_handle(data[2])
126                value = name_displayer.sorted_name(person.primary_name)
127            else:
128                value = ""
129            self.set_cached_value(handle, "SORT_FATHER", value)
130        return value
131
132    def column_mother(self, data):
133        handle = data[0]
134        cached, value = self.get_cached_value(handle, "MOTHER")
135        if not cached:
136            if data[3]:
137                person = self.db.get_person_from_handle(data[3])
138                value = name_displayer.display_name(person.primary_name)
139            else:
140                value = ""
141            self.set_cached_value(handle, "MOTHER", value)
142        return value
143
144    def sort_mother(self, data):
145        handle = data[0]
146        cached, value = self.get_cached_value(handle, "SORT_MOTHER")
147        if not cached:
148            if data[3]:
149                person = self.db.get_person_from_handle(data[3])
150                value = name_displayer.sorted_name(person.primary_name)
151            else:
152                value = ""
153            self.set_cached_value(handle, "SORT_MOTHER", value)
154        return value
155
156    def column_type(self, data):
157        return str(FamilyRelType(data[5]))
158
159    def column_marriage(self, data):
160        handle = data[0]
161        cached, value = self.get_cached_value(handle, "MARRIAGE")
162        if not cached:
163            family = self.db.get_family_from_handle(data[0])
164            event = get_marriage_or_fallback(self.db, family, "<i>%s</i>")
165            if event:
166                if event.date.format:
167                    value = event.date.format % displayer.display(event.date)
168                elif not get_date_valid(event):
169                    value = invalid_date_format % displayer.display(event.date)
170                else:
171                    value = "%s" % displayer.display(event.date)
172            else:
173                value = ''
174            self.set_cached_value(handle, "MARRIAGE", value)
175        return value
176
177    def sort_marriage(self, data):
178        handle = data[0]
179        cached, value = self.get_cached_value(handle, "SORT_MARRIAGE")
180        if not cached:
181            family = self.db.get_family_from_handle(data[0])
182            event = get_marriage_or_fallback(self.db, family)
183            if event:
184                value = "%09d" % event.date.get_sort_value()
185            else:
186                value = ''
187            self.set_cached_value(handle, "SORT_MARRIAGE", value)
188        return value
189
190    def column_id(self, data):
191        return data[1]
192
193    def column_private(self, data):
194        if data[14]:
195            return 'gramps-lock'
196        else:
197            # There is a problem returning None here.
198            return ''
199
200    def sort_change(self, data):
201        return "%012x" % data[12]
202
203    def column_change(self, data):
204        return format_time(data[12])
205
206    def get_tag_name(self, tag_handle):
207        """
208        Return the tag name from the given tag handle.
209        """
210        cached, value = self.get_cached_value(tag_handle, "TAG_NAME")
211        if not cached:
212            value = self.db.get_tag_from_handle(tag_handle).get_name()
213            self.set_cached_value(tag_handle, "TAG_NAME", value)
214        return value
215
216    def column_tag_color(self, data):
217        """
218        Return the tag color.
219        """
220        tag_handle = data[0]
221        cached, tag_color = self.get_cached_value(tag_handle, "TAG_COLOR")
222        if not cached:
223            tag_color = ""
224            tag_priority = None
225            for handle in data[13]:
226                tag = self.db.get_tag_from_handle(handle)
227                this_priority = tag.get_priority()
228                if tag_priority is None or this_priority < tag_priority:
229                    tag_color = tag.get_color()
230                    tag_priority = this_priority
231            self.set_cached_value(tag_handle, "TAG_COLOR", tag_color)
232        return tag_color
233
234    def column_tags(self, data):
235        """
236        Return the sorted list of tags.
237        """
238        tag_list = list(map(self.get_tag_name, data[13]))
239        # TODO for Arabic, should the next line's comma be translated?
240        return ', '.join(sorted(tag_list, key=glocale.sort_key))
241