1# 2# Gramps - a GTK+/GNOME based genealogy program 3# 4# Copyright (C) 2003-2006, 2008 Donald N. Allingham 5# Copyright (C) 2008 Brian G. Matherly 6# Copyright (C) 2010 Jakim Friant 7# 8# This program is free software; you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation; either version 2 of the License, or 11# (at your option) any later version. 12# 13# This program is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16# GNU General Public License for more details. 17# 18# You should have received a copy of the GNU General Public License 19# along with this program; if not, write to the Free Software 20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21# 22 23"Export to Web Family Tree" 24 25#------------------------------------------------------------------------- 26# 27# standard python modules 28# 29#------------------------------------------------------------------------- 30 31#------------------------------------------------------------------------ 32# 33# Set up logging 34# 35#------------------------------------------------------------------------ 36import logging 37from collections import abc 38log = logging.getLogger(".WriteFtree") 39 40#------------------------------------------------------------------------- 41# 42# Gramps modules 43# 44#------------------------------------------------------------------------- 45# keep the following line even though not obviously used (works on import) 46from gramps.gui.plug.export import WriterOptionBox 47from gramps.gui.dialog import ErrorDialog 48from gramps.gen.const import GRAMPS_LOCALE as glocale 49_ = glocale.translation.gettext 50 51 52#------------------------------------------------------------------------- 53# 54# writeData 55# 56#------------------------------------------------------------------------- 57def writeData(database, filename, user, option_box=None): 58 """ function to export Web Family Tree file """ 59 writer = FtreeWriter(database, filename, user, option_box) 60 return writer.export_data() 61 62 63#------------------------------------------------------------------------- 64# 65# FtreeWriter 66# 67#------------------------------------------------------------------------- 68class FtreeWriter: 69 """ Export a Web Family Tree format file """ 70 def __init__(self, database, filename, user, option_box=None): 71 self.db = database 72 self.filename = filename 73 self.user = user 74 self.option_box = option_box 75 # is callback is really callable? 76 if isinstance(self.user.callback, abc.Callable): 77 self.update = self.update_real 78 else: 79 self.update = self.update_empty 80 81 if option_box: 82 self.option_box.parse_options() 83 self.db = option_box.get_filtered_database(self.db) 84 85 self.plist = self.db.get_person_handles() 86 self.plist.sort() 87 # the following are used to update the progress meter 88 self.total = 2 * len(self.plist) 89 self.count = 0 90 self.oldval = 0 # we only update when percentage changes 91 92 def update_empty(self): 93 """ used when no callback is present """ 94 pass 95 96 def update_real(self): 97 """ Progress update """ 98 self.count += 1 99 newval = int(100 * self.count / self.total) 100 if newval != self.oldval: 101 self.user.callback(newval) 102 self.oldval = newval 103 104 def export_data(self): 105 """ main export processing """ 106 name_map = {} 107 id_map = {} 108 id_name = {} 109 110 for key in self.plist: 111 self.update() 112 pnam = self.db.get_person_from_handle(key).get_primary_name() 113 snam = pnam.get_surname() 114 items = pnam.get_first_name().split() 115 nam = ("%s %s" % (items[0], snam)) if items else snam 116 117 count = -1 118 if nam in name_map: 119 count = 0 120 while 1: 121 nam_num = "%s%d" % (nam, count) 122 if nam_num not in name_map: 123 break 124 count += 1 125 name_map[nam_num] = key 126 id_map[key] = nam_num 127 else: 128 name_map[nam] = key 129 id_map[key] = nam 130 id_name[key] = get_name(pnam, snam, count) 131 132 try: 133 with open(self.filename, "w", encoding='utf_8') as file: 134 return self._export_data(file, id_name, id_map) 135 except IOError as msg: 136 msg2 = _("Could not create %s") % self.filename 137 ErrorDialog(msg2, str(msg), parent=self.option_box.window) 138 return False 139 140 def _export_data(self, file, id_name, id_map): 141 """ file export processing """ 142 for key in self.plist: 143 self.update() 144 pers = self.db.get_person_from_handle(key) 145 name = id_name[key] 146 father = mother = email = web = "" 147 148 family_handle = pers.get_main_parents_family_handle() 149 if family_handle: 150 family = self.db.get_family_from_handle(family_handle) 151 if family.get_father_handle() and \ 152 family.get_father_handle() in id_map: 153 father = id_map[family.get_father_handle()] 154 if family.get_mother_handle() and \ 155 family.get_mother_handle() in id_map: 156 mother = id_map[family.get_mother_handle()] 157 158 # 159 # Calculate Date 160 # 161 birth_ref = pers.get_birth_ref() 162 death_ref = pers.get_death_ref() 163 if birth_ref: 164 birth_event = self.db.get_event_from_handle(birth_ref.ref) 165 birth = birth_event.get_date_object() 166 else: 167 birth = None 168 if death_ref: 169 death_event = self.db.get_event_from_handle(death_ref.ref) 170 death = death_event.get_date_object() 171 else: 172 death = None 173 174 #if self.restrict: 175 # alive = probably_alive(pers, self.db) 176 #else: 177 # alive = 0 178 179 if birth: 180 if death: 181 dates = "%s-%s" % (fdate(birth), fdate(death)) 182 else: 183 dates = fdate(birth) 184 else: 185 if death: 186 dates = fdate(death) 187 else: 188 dates = "" 189 190 file.write('%s;%s;%s;%s;%s;%s\n' % 191 (name, father, mother, email, web, dates)) 192 193 return True 194 195 196def fdate(val): 197 """ return properly formatted date """ 198 if val.get_year_valid(): 199 if val.get_month_valid(): 200 if val.get_day_valid(): 201 return "%d/%d/%d" % (val.get_day(), val.get_month(), 202 val.get_year()) 203 return "%d/%d" % (val.get_month(), val.get_year()) 204 return "%d" % val.get_year() 205 return "" 206 207 208def get_name(name, surname, count): 209 """returns a name string built from the components of the Name 210 instance, in the form of Firstname Surname""" 211 212 return (name.first_name + ' ' + 213 surname + 214 (str(count) if count != -1 else '') + 215 (', ' + name.suffix if name.suffix else '')) 216