Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b5508d997 | ||
|
|
77455f2776 | ||
|
|
5ca248aa14 | ||
|
|
d1b9344373 | ||
|
|
081c300b75 | ||
|
|
35d494f49e | ||
|
|
658284d692 | ||
|
|
900edf379c | ||
|
|
4ceee5b350 | ||
|
|
3154bbaa50 | ||
|
|
e3147bc8a5 | ||
|
|
9fcf2bf560 | ||
|
|
626e1ec24d | ||
|
|
9bc9cf6a47 | ||
|
|
94efebf36c | ||
|
|
f91eb31d88 | ||
|
|
03d5e3f4bc | ||
|
|
5bc355ad0c | ||
|
|
47ff14af65 | ||
|
|
60a4ce9f4a | ||
|
|
959693bc84 | ||
|
|
395e46aaab | ||
|
|
c0b534fe1d | ||
|
|
bdd3a553c0 | ||
|
|
3418ac3bd2 | ||
|
|
aff06c9b49 | ||
|
|
bf7182ed8f | ||
|
|
dc5cfb7f91 | ||
|
|
ea9df739a4 | ||
|
|
e6f6d5d00c | ||
|
|
77d3cf1967 | ||
|
|
e80a74d72a | ||
|
|
1baf7070a3 | ||
|
|
f1e2d15ebb | ||
|
|
a8ab3b5f4e | ||
|
|
403bea5f2c | ||
|
|
ca3dba5dd9 | ||
|
|
3f87bdec6e | ||
|
|
848114ea4e | ||
|
|
ef37b3c6a6 | ||
|
|
0fe26ef415 | ||
|
|
2f9341dcb8 | ||
|
|
77f96037fa | ||
|
|
1cb6f2f3c8 | ||
|
|
43fa619ebc | ||
|
|
db4e0aafb8 | ||
|
|
09e9872206 | ||
|
|
796b778bf0 | ||
|
|
174886e40a | ||
|
|
dd1f244d24 | ||
|
|
0f7623be22 | ||
|
|
1a27f856c5 | ||
|
|
d3993f57ff | ||
|
|
af788956aa | ||
|
|
96efc4ee45 | ||
|
|
359192efb0 | ||
|
|
8e841be786 | ||
|
|
9d207fd48f | ||
|
|
924acb11ff |
@@ -1,3 +1,13 @@
|
||||
Version 3.2.5 -- the "I intend to live forever" bug fix release.
|
||||
* fix Gramps so it again runs with Python 2.5
|
||||
* write all notes and sources to gedcom files
|
||||
* cli fixes
|
||||
* GeneWeb and LegacyGedcom fixes
|
||||
* NarrativeWeb fixes
|
||||
* memory leak fixes
|
||||
* various other small fixes
|
||||
* many translation updates
|
||||
|
||||
Version 3.2.4 -- the "Tententen" bug fix release.
|
||||
* fix a crash on newer distro's after an export is finished
|
||||
* styled notes cleanup and consistency improvement (nar web behaves like the pdf/html output of reports)
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ dnl May need to run automake && aclocal first
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
dnl NOTE: arg to macro below becomes the "VERSION"
|
||||
AC_INIT(gramps, 3.2.4, [gramps-bugs@lists.sourceforge.net])
|
||||
AC_INIT(gramps, 3.2.5, [gramps-bugs@lists.sourceforge.net])
|
||||
AC_CONFIG_SRCDIR(configure.in)
|
||||
AM_INIT_AUTOMAKE([1.6.3 foreign])
|
||||
|
||||
|
||||
+663
-548
File diff suppressed because it is too large
Load Diff
+3318
-3596
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,7 @@ pkgdata_PYTHON = \
|
||||
_Date_pt.py\
|
||||
_Date_ru.py\
|
||||
_Date_sk.py\
|
||||
_Date_sl.py\
|
||||
_Date_sr.py\
|
||||
_Date_sv.py\
|
||||
_DateDisplay.py\
|
||||
|
||||
+56
-57
@@ -187,13 +187,12 @@ class DateDisplayRU(DateDisplay):
|
||||
"""
|
||||
Russian language date display class.
|
||||
"""
|
||||
# TODO: Translate these month strings:
|
||||
long_months = ( u"", u"January", u"February", u"March", u"April", u"May",
|
||||
u"June", u"July", u"August", u"September", u"October",
|
||||
u"November", u"December" )
|
||||
long_months = ( u"", u"января", u"февраля", u"марта", u"апреля", u"мая",
|
||||
u"июня", u"июля", u"августа", u"сентября", u"октября",
|
||||
u"ноября", u"декабря" )
|
||||
|
||||
short_months = ( u"", u"Jan", u"Feb", u"Mar", u"Apr", u"May", u"Jun",
|
||||
u"Jul", u"Aug", u"Sep", u"Oct", u"Nov", u"Dec" )
|
||||
short_months = ( u"", u"янв", u"фев", u"мар", u"апр", u"мая", u"июн",
|
||||
u"июл", u"авг", u"сен", u"окт", u"ноя", u"дек" )
|
||||
|
||||
calendar = (
|
||||
u"",
|
||||
@@ -202,7 +201,7 @@ class DateDisplayRU(DateDisplay):
|
||||
u"республиканский",
|
||||
u"персидский",
|
||||
u"исламский",
|
||||
u"Swedish"
|
||||
u"шведский"
|
||||
)
|
||||
|
||||
_mod_str = (
|
||||
@@ -222,65 +221,65 @@ class DateDisplayRU(DateDisplay):
|
||||
)
|
||||
|
||||
hebrew = ( u"",
|
||||
u"Тишрей",
|
||||
u"Хешван",
|
||||
u"Кислев",
|
||||
u"Тевет",
|
||||
u"Шеват",
|
||||
u"Адар",
|
||||
u"Адар бет",
|
||||
u"Нисан",
|
||||
u"Ияр",
|
||||
u"Сиван",
|
||||
u"Таммуз",
|
||||
u"Ав",
|
||||
u"Элул",
|
||||
u"тишрея",
|
||||
u"хешвана",
|
||||
u"кислева",
|
||||
u"тевета",
|
||||
u"шевата",
|
||||
u"адара",
|
||||
u"адар бета",
|
||||
u"нисана",
|
||||
u"ияра",
|
||||
u"сивана",
|
||||
u"таммуза",
|
||||
u"ава",
|
||||
u"элула",
|
||||
)
|
||||
|
||||
islamic = ( u"",
|
||||
u"Мухаррам",
|
||||
u"Сафар",
|
||||
u"Раби-аль-авваль",
|
||||
u"Раби-ассани",
|
||||
u"Джумада-аль-уля",
|
||||
u"Джумада-аль-ахира",
|
||||
u"Раджаб",
|
||||
u"Шаабан",
|
||||
u"Рамадан",
|
||||
u"Шавваль",
|
||||
u"Зуль-каада",
|
||||
u"Зуль-хиджжа",
|
||||
u"мухаррама",
|
||||
u"сафара",
|
||||
u"раби-аль-авваля",
|
||||
u"раби-ассани",
|
||||
u"джумада-аль-уля",
|
||||
u"джумада-аль-ахира",
|
||||
u"раджаба",
|
||||
u"шаабана",
|
||||
u"рамадана",
|
||||
u"шаввальа",
|
||||
u"зуль-каада",
|
||||
u"зуль-хиджжа",
|
||||
)
|
||||
|
||||
persian = ( u"",
|
||||
u"Фарвардин",
|
||||
u"Урдбихишт",
|
||||
u"Хурдад",
|
||||
u"Тир",
|
||||
u"Мурдад",
|
||||
u"Шахривар",
|
||||
u"Михр",
|
||||
u"Абан",
|
||||
u"Азар",
|
||||
u"Дай",
|
||||
u"Бахман",
|
||||
u"Исфаидармуз",
|
||||
u"фарвардина",
|
||||
u"урдбихишта",
|
||||
u"хурдада",
|
||||
u"тира",
|
||||
u"мурдада",
|
||||
u"шахривара",
|
||||
u"михра",
|
||||
u"абана",
|
||||
u"азара",
|
||||
u"дайа",
|
||||
u"бахмана",
|
||||
u"исфаидармуза",
|
||||
)
|
||||
|
||||
french = ( u"",
|
||||
u"Вандемьер",
|
||||
u"Брюмер",
|
||||
u"Фример",
|
||||
u"Нивоз",
|
||||
u"Плювиоз",
|
||||
u"Вантоз",
|
||||
u"Жерминаль",
|
||||
u"Флореаль",
|
||||
u"Прериаль",
|
||||
u"Мессидор",
|
||||
u"Термидор",
|
||||
u"Фрюктидор",
|
||||
u"Дополнит."
|
||||
u"вандемьера",
|
||||
u"брюмера",
|
||||
u"фримера",
|
||||
u"нивоза",
|
||||
u"плювиоза",
|
||||
u"вантоза",
|
||||
u"жерминаля",
|
||||
u"флореаля",
|
||||
u"прериаля",
|
||||
u"мессидора",
|
||||
u"термидора",
|
||||
u"фрюктидора",
|
||||
u"дополнит."
|
||||
)
|
||||
|
||||
def display(self, date):
|
||||
|
||||
@@ -0,0 +1,313 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2004-2007 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# Slovenian version 2010 by Bernard Banko, based on croatian one by Josip
|
||||
|
||||
"""
|
||||
Slovenian-specific classes for parsing and displaying dates.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import re
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gen.lib import Date
|
||||
from _DateParser import DateParser
|
||||
from _DateDisplay import DateDisplay
|
||||
from _DateHandler import register_datehandler
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Slovenian parser
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class DateParserSL(DateParser):
|
||||
"""
|
||||
Converts a text string into a Date object
|
||||
"""
|
||||
month_to_int = DateParser.month_to_int
|
||||
|
||||
month_to_int[u"januar"] = 1
|
||||
month_to_int[u"januarja"] = 1
|
||||
month_to_int[u"januarjem"] = 1
|
||||
month_to_int[u"jan"] = 1
|
||||
month_to_int[u"i"] = 1
|
||||
|
||||
month_to_int[u"februar"] = 2
|
||||
month_to_int[u"februarjem"] = 2
|
||||
month_to_int[u"februarja"] = 2
|
||||
month_to_int[u"feb"] = 2
|
||||
month_to_int[u"ii"] = 2
|
||||
|
||||
month_to_int[u"mar"] = 3
|
||||
month_to_int[u"marcem"] = 3
|
||||
month_to_int[u"marec"] = 3
|
||||
month_to_int[u"marca"] = 3
|
||||
month_to_int[u"iii"] = 3
|
||||
|
||||
month_to_int[u"apr"] = 4
|
||||
month_to_int[u"april"] = 4
|
||||
month_to_int[u"aprilom"] = 4
|
||||
month_to_int[u"aprila"] = 4
|
||||
month_to_int[u"iv"] = 4
|
||||
|
||||
month_to_int[u"maj"] = 5
|
||||
month_to_int[u"maja"] = 5
|
||||
month_to_int[u"majem"] = 5
|
||||
month_to_int[u"v"] = 5
|
||||
|
||||
month_to_int[u"jun"] = 6
|
||||
month_to_int[u"junij"] = 6
|
||||
month_to_int[u"junijem"] = 6
|
||||
month_to_int[u"junija"] = 6
|
||||
month_to_int[u"vi"] = 6
|
||||
|
||||
month_to_int[u"jul"] = 7
|
||||
month_to_int[u"julij"] = 7
|
||||
month_to_int[u"julijem"] = 7
|
||||
month_to_int[u"julija"] = 7
|
||||
month_to_int[u"vii"] = 7
|
||||
|
||||
month_to_int[u"avg"] = 8
|
||||
month_to_int[u"avgust"] = 8
|
||||
month_to_int[u"avgustom"] = 8
|
||||
month_to_int[u"avgusta"] = 8
|
||||
month_to_int[u"viii"] = 8
|
||||
|
||||
month_to_int[u"sep"] = 9
|
||||
month_to_int[u"sept"] = 9
|
||||
month_to_int[u"september"] = 9
|
||||
month_to_int[u"septembrom"] = 9
|
||||
month_to_int[u"septembra"] = 9
|
||||
month_to_int[u"ix"] = 9
|
||||
|
||||
month_to_int[u"okt"] = 10
|
||||
month_to_int[u"oktober"] = 10
|
||||
month_to_int[u"oktobrom"] = 10
|
||||
month_to_int[u"oktobra"] = 10
|
||||
month_to_int[u"x"] = 10
|
||||
|
||||
month_to_int[u"nov"] = 11
|
||||
month_to_int[u"november"] = 11
|
||||
month_to_int[u"novembrom"] = 11
|
||||
month_to_int[u"novembra"] = 11
|
||||
month_to_int[u"xi"] = 11
|
||||
|
||||
month_to_int[u"dec"] = 12
|
||||
month_to_int[u"december"] = 12
|
||||
month_to_int[u"decembrom"] = 12
|
||||
month_to_int[u"decembra"] = 12
|
||||
month_to_int[u"xii"] = 12
|
||||
|
||||
modifier_to_int = {
|
||||
u'pred' : Date.MOD_BEFORE,
|
||||
u'pr.' : Date.MOD_BEFORE,
|
||||
u'po' : Date.MOD_AFTER,
|
||||
u'okoli' : Date.MOD_ABOUT,
|
||||
u'okrog' : Date.MOD_ABOUT,
|
||||
u'okr.' : Date.MOD_ABOUT,
|
||||
u'ok.' : Date.MOD_ABOUT,
|
||||
u'cca.' : Date.MOD_ABOUT,
|
||||
u'cca' : Date.MOD_ABOUT,
|
||||
u'circa' : Date.MOD_ABOUT,
|
||||
u'ca.' : Date.MOD_ABOUT,
|
||||
}
|
||||
|
||||
calendar_to_int = {
|
||||
u'gregorijanski' : Date.CAL_GREGORIAN,
|
||||
u'greg.' : Date.CAL_GREGORIAN,
|
||||
u'julijanski' : Date.CAL_JULIAN,
|
||||
u'jul.' : Date.CAL_JULIAN,
|
||||
u'hebrejski' : Date.CAL_HEBREW,
|
||||
u'hebr.' : Date.CAL_HEBREW,
|
||||
u'islamski' : Date.CAL_ISLAMIC,
|
||||
u'isl.' : Date.CAL_ISLAMIC,
|
||||
u'francoski republikanski': Date.CAL_FRENCH,
|
||||
u'franc.' : Date.CAL_FRENCH,
|
||||
u'perzijski' : Date.CAL_PERSIAN,
|
||||
u'perz. ' : Date.CAL_PERSIAN,
|
||||
u'švedski' : Date.CAL_SWEDISH,
|
||||
u'šved.' : Date.CAL_SWEDISH,
|
||||
}
|
||||
|
||||
quality_to_int = {
|
||||
u'približno' : Date.QUAL_ESTIMATED,
|
||||
u'pribl.' : Date.QUAL_ESTIMATED,
|
||||
u'izračunano' : Date.QUAL_CALCULATED,
|
||||
u'izrač.' : Date.QUAL_CALCULATED,
|
||||
}
|
||||
|
||||
bce = ["pred našim štetjem", "pred Kristusom",
|
||||
"p.n.š.", "p. n. š.", "pr.Kr.", "pr. Kr."] + DateParser.bce
|
||||
|
||||
def init_strings(self):
|
||||
"""
|
||||
compiles regular expression strings for matching dates
|
||||
"""
|
||||
DateParser.init_strings(self)
|
||||
# match 'Day. MONTH year.' format with or without dots
|
||||
self._text2 = re.compile('(\d+)?\.?\s*?%s\.?\s*((\d+)(/\d+)?)?\s*\.?$'
|
||||
% self._mon_str, re.IGNORECASE)
|
||||
# match Day.Month.Year.
|
||||
self._numeric = re.compile("((\d+)[/\.-])?\s*((\d+)[/\.-])?\s*(\d+)\.?$")
|
||||
|
||||
self._span = re.compile("od\s+(?P<start>.+)\s+do\s+(?P<stop>.+)",
|
||||
re.IGNORECASE)
|
||||
self._range = re.compile(
|
||||
u"med\s+(?P<start>.+)\s+in\s+(?P<stop>.+)",
|
||||
re.IGNORECASE)
|
||||
self._jtext2 = re.compile('(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?'\
|
||||
% self._jmon_str, re.IGNORECASE)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Slovenian display
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class DateDisplaySL(DateDisplay):
|
||||
"""
|
||||
Slovenian language date display class.
|
||||
"""
|
||||
long_months = ( u"", u"januarja", u"februarja", u"marca",u"aprila",
|
||||
u"maja", u"junija", u"julija", u"avgusta", u"septembra",
|
||||
u"oktobra", u"novembra", u"decembra"
|
||||
)
|
||||
|
||||
short_months = ( u"", u"jan", u"feb", u"mar", u"apr", u"maj", u"jun",
|
||||
u"jul", u"avg", u"sep", u"okt", u"nov", u"dec"
|
||||
)
|
||||
|
||||
calendar = (
|
||||
"", u"julijanski", u"hebrejski",
|
||||
u"francoski republikanski", u"perzijski", u"islamski",
|
||||
u"švedski"
|
||||
)
|
||||
|
||||
_mod_str = ("", "pred ", "po ", "okrog ", "", "", "")
|
||||
|
||||
_qual_str = ("", "približno ", "izračunano ")
|
||||
|
||||
_bce_str = "%s p.n.š."
|
||||
|
||||
formats = (
|
||||
"ISO (leto-mm-dd)",
|
||||
"številčno",
|
||||
"dan. mes. leto",
|
||||
"dan. mesec leto"
|
||||
)
|
||||
|
||||
def _display_gregorian(self, date_val):
|
||||
"""
|
||||
display gregorian calendar date in different format
|
||||
"""
|
||||
year = self._slash_year(date_val[2], date_val[3])
|
||||
if self.format == 0:
|
||||
return self.display_iso(date_val)
|
||||
elif self.format == 1:
|
||||
# D. M. YYYY
|
||||
if date_val[3]:
|
||||
return self.display_iso(date_val)
|
||||
else:
|
||||
if date_val[0] == 0 and date_val[1] == 0:
|
||||
value = str(date_val[2])
|
||||
else:
|
||||
value = self._tformat.replace('%m', str(date_val[1]))
|
||||
value = value.replace('%d', str(date_val[0]))
|
||||
value = value.replace('%Y', str(date_val[2]))
|
||||
value = value.replace('-', '. ')
|
||||
elif self.format == 2:
|
||||
# D. mon. YYYY
|
||||
if date_val[0] == 0:
|
||||
if date_val[1] == 0:
|
||||
value = year
|
||||
else:
|
||||
value = "%s. %s" % (self.short_months[date_val[1]], year)
|
||||
else:
|
||||
value = "%d. %s. %s" % (date_val[0],
|
||||
self.short_months[date_val[1]], year)
|
||||
else:
|
||||
# D. month YYYY
|
||||
if date_val[0] == 0:
|
||||
if date_val[1] == 0:
|
||||
value = "%s." % year
|
||||
else:
|
||||
value = "%s %s" % (self.long_months[date_val[1]], year)
|
||||
else:
|
||||
value = "%d. %s %s" % (
|
||||
date_val[0],self.long_months[date_val[1]], year)
|
||||
if date_val[2] < 0:
|
||||
return self._bce_str % value
|
||||
else:
|
||||
return value
|
||||
|
||||
def display(self, date):
|
||||
"""
|
||||
Return a text string representing the date.
|
||||
"""
|
||||
mod = date.get_modifier()
|
||||
cal = date.get_calendar()
|
||||
qual = date.get_quality()
|
||||
start = date.get_start_date()
|
||||
newyear = date.get_new_year()
|
||||
|
||||
qual_str = self._qual_str[qual]
|
||||
|
||||
if mod == Date.MOD_TEXTONLY:
|
||||
return date.get_text()
|
||||
elif start == Date.EMPTY:
|
||||
return u""
|
||||
elif mod == Date.MOD_SPAN:
|
||||
d_1 = self.display_cal[cal](start)
|
||||
d_2 = self.display_cal[cal](date.get_stop_date())
|
||||
scal = self.format_extras(cal, newyear)
|
||||
return u"%sod %s do %s%s" % (qual_str, d_1, d_2, scal)
|
||||
elif mod == Date.MOD_RANGE:
|
||||
d_1 = self.display_cal[cal](start)
|
||||
d_2 = self.display_cal[cal](date.get_stop_date())
|
||||
scal = self.format_extras(cal, newyear)
|
||||
date_string = u"%smed %s in %s%s" % (qual_str, d_1, d_2, scal)
|
||||
date_string = date_string.replace(u"a ",u"em ") #to correct declination
|
||||
date_string = date_string.replace(u"lem ",u"lom ")
|
||||
date_string = date_string.replace(u"rem ",u"rom ")
|
||||
date_string = date_string.replace(u"tem ",u"tom ")
|
||||
return date_string
|
||||
else:
|
||||
text = self.display_cal[date.get_calendar()](start)
|
||||
scal = self.format_extras(cal, newyear)
|
||||
date_string = "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal)
|
||||
return date_string
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Register classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
register_datehandler(("sl", "SL", "sl_SI", "slovenščina", "slovenian", "Slovenian",
|
||||
"sl_SI.UTF8", "sl_SI.UTF-8", "sl_SI.utf-8", "sl_SI.utf8"),
|
||||
DateParserSL, DateDisplaySL)
|
||||
@@ -45,6 +45,7 @@ import _Date_pl
|
||||
import _Date_pt
|
||||
import _Date_ru
|
||||
import _Date_sk
|
||||
import _Date_sl
|
||||
import _Date_sr
|
||||
import _Date_sv
|
||||
|
||||
|
||||
@@ -61,8 +61,10 @@ class GenericFilter(object):
|
||||
return False
|
||||
|
||||
def is_empty(self):
|
||||
return len(self.flist) == 0 or \
|
||||
(len(self.flist) == 1 and self.flist[0].is_empty())
|
||||
return (len(self.flist) == 0 or
|
||||
(len(self.flist) == 1 and
|
||||
((self.flist[0].is_empty() and not self.invert) or
|
||||
(not self.flist[0].is_empty() and self.invert))))
|
||||
|
||||
def set_logical_op(self, val):
|
||||
if val in GenericFilter.logical_functions:
|
||||
|
||||
@@ -57,7 +57,15 @@ class SearchBar(object):
|
||||
self.filter_model = gtk.ListStore(gobject.TYPE_STRING,
|
||||
gobject.TYPE_INT,
|
||||
gobject.TYPE_BOOLEAN)
|
||||
|
||||
|
||||
def destroy(self):
|
||||
"""Unset all things that can block garbage collection.
|
||||
"""
|
||||
self.on_apply_callback = None
|
||||
self.apply_done_callback = None
|
||||
self.dbstate = None
|
||||
self.uistate = None
|
||||
|
||||
def build( self):
|
||||
self.filterbar.set_spacing(4)
|
||||
self.filter_list.connect('changed', self.filter_changed)
|
||||
|
||||
@@ -151,4 +151,7 @@ class LRU(object):
|
||||
"""
|
||||
Empties LRU
|
||||
"""
|
||||
for obj, node in self.data.iteritems():
|
||||
node.prev = None
|
||||
node.next = None
|
||||
self.data.clear()
|
||||
|
||||
@@ -187,7 +187,7 @@ class ErrorDialog(gtk.MessageDialog):
|
||||
|
||||
class RunDatabaseRepair(ErrorDialog):
|
||||
def __init__(self, msg, parent=None):
|
||||
msg = unicode(msg.decode(sys.getfilesystemencoding()))
|
||||
msg = unicode(str(msg).decode(sys.getfilesystemencoding()))
|
||||
ErrorDialog.__init__(
|
||||
self,
|
||||
_('Error detected in database'),
|
||||
@@ -199,7 +199,7 @@ class RunDatabaseRepair(ErrorDialog):
|
||||
|
||||
class DBErrorDialog(ErrorDialog):
|
||||
def __init__(self, msg, parent=None):
|
||||
msg = unicode(msg.decode(sys.getfilesystemencoding()))
|
||||
msg = unicode(str(msg).decode(sys.getfilesystemencoding()))
|
||||
ErrorDialog.__init__(
|
||||
self,
|
||||
_("Low level database corruption detected"),
|
||||
|
||||
@@ -371,21 +371,26 @@ class CommandLineReport(object):
|
||||
opt = self.options_help[key]
|
||||
# Make the output nicer to read, assume that tab has 8 spaces
|
||||
tabs = '\t' if len(key) < 10 else '\t'*2
|
||||
print " %s%s%s (%s)" % (key, tabs, opt[1], opt[0])
|
||||
optmsg = " %s%s%s (%s)" % (key, tabs, opt[1], opt[0])
|
||||
print optmsg.encode(sys.getfilesystemencoding())
|
||||
else:
|
||||
print " %s" % key
|
||||
optmsg = " %s" % key
|
||||
print optmsg.encode(sys.getfilesystemencoding())
|
||||
print " Use 'show=option' to see description and acceptable values"
|
||||
elif self.show in self.options_help:
|
||||
opt = self.options_help[self.show]
|
||||
tabs = '\t' if len(self.show) < 10 else '\t'*2
|
||||
print ' %s%s%s%s' % (self.show, tabs, opt[0], opt[1])
|
||||
optmsg = ' %s%s%s%s' % (self.show, tabs, opt[0], opt[1])
|
||||
print optmsg.encode(sys.getfilesystemencoding())
|
||||
print " Available values are:"
|
||||
vals = opt[2]
|
||||
if isinstance(vals, (list, tuple)):
|
||||
for val in vals:
|
||||
print " %s" % val
|
||||
optmsg = " %s" % val
|
||||
print optmsg.encode(sys.getfilesystemencoding())
|
||||
else:
|
||||
print " %s" % opt[2]
|
||||
optmsg = " %s" % opt[2]
|
||||
print optmsg.encode(sys.getfilesystemencoding())
|
||||
|
||||
else:
|
||||
#there was a show option given, but the option is invalid
|
||||
|
||||
+6
-5
@@ -333,12 +333,12 @@ def get_unicode_path_from_file_chooser(path):
|
||||
:rtype: unicode
|
||||
:returns: The Unicode version of path.
|
||||
"""
|
||||
# Don't make unicode of unicode
|
||||
if isinstance(path, unicode):
|
||||
# make omly unicode of path of type 'str'
|
||||
if not (isinstance(path, str)):
|
||||
return path
|
||||
|
||||
if constfunc.win():
|
||||
# in windows filechooser returns officially utf-8, not filesystemencoding
|
||||
# in windows filechooser returns officially utf-8, not filesystemencoding
|
||||
try:
|
||||
return unicode(path)
|
||||
except:
|
||||
@@ -360,7 +360,8 @@ def get_unicode_path_from_env_var(path):
|
||||
:rtype: unicode
|
||||
:returns: The Unicode version of path.
|
||||
"""
|
||||
if isinstance(path, unicode):
|
||||
# make omly unicode of path of type 'str'
|
||||
if not (isinstance(path, str)):
|
||||
return path
|
||||
|
||||
if constfunc.win():
|
||||
@@ -844,7 +845,7 @@ def probably_alive(person, db,
|
||||
"""
|
||||
Return true if the person may be alive on current_date.
|
||||
|
||||
This works by a process of emlimination. If we can't find a good
|
||||
This works by a process of elimination. If we can't find a good
|
||||
reason to believe that someone is dead then we assume they must
|
||||
be alive.
|
||||
|
||||
|
||||
+27
-10
@@ -94,7 +94,9 @@ class ArgHandler(object):
|
||||
if self.errorfunc:
|
||||
self.errorfunc(string)
|
||||
else:
|
||||
print string
|
||||
# Need to convert to str before printing
|
||||
# For non latin characters in Windows path/file/user names
|
||||
print string.encode(sys.getfilesystemencoding())
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Argument parser: sorts out given arguments
|
||||
@@ -115,8 +117,8 @@ class ArgHandler(object):
|
||||
"""
|
||||
if value is None:
|
||||
return None
|
||||
value = Utils.get_unicode_path_from_env_var(value)
|
||||
db_path = self.__deduce_db_path(value)
|
||||
|
||||
if db_path:
|
||||
# We have a potential database path.
|
||||
# Check if it is good.
|
||||
@@ -134,6 +136,9 @@ class ArgHandler(object):
|
||||
Handle the "-i" or "--import" option.
|
||||
Only Files supported by a plugin can be imported, so not Family Trees.
|
||||
"""
|
||||
# Need to convert path/filename to unicode before openingh
|
||||
# For non latin characters in Windows path/file/user names
|
||||
value = Utils.get_unicode_path_from_env_var(value)
|
||||
fname = value
|
||||
fullpath = os.path.abspath(os.path.expanduser(fname))
|
||||
if not os.path.exists(fullpath):
|
||||
@@ -168,6 +173,9 @@ class ArgHandler(object):
|
||||
"""
|
||||
if self.gui:
|
||||
return
|
||||
# Need to covert path/filename to unicode before openingh
|
||||
# For non latin characters in Windows path/file/user names
|
||||
value = Utils.get_unicode_path_from_env_var(value)
|
||||
fname = value
|
||||
fullpath = os.path.abspath(os.path.expanduser(fname))
|
||||
if os.path.exists(fullpath):
|
||||
@@ -176,8 +184,9 @@ class ArgHandler(object):
|
||||
{'name' : fullpath})
|
||||
answer = None
|
||||
while not answer:
|
||||
answer = raw_input(_('OK to overwrite? (yes/no) '))
|
||||
if answer.upper() in ('Y', 'YES', _('YES')):
|
||||
answer = raw_input(_('OK to overwrite? (yes/no) ') \
|
||||
.encode(sys.getfilesystemencoding()))
|
||||
if answer.upper() in ('Y', 'YES', _('YES').upper()):
|
||||
self.__error( _("Will overwrite the existing file: %s")
|
||||
% fullpath)
|
||||
else:
|
||||
@@ -310,7 +319,11 @@ class ArgHandler(object):
|
||||
self.cl_action(action, options_str)
|
||||
|
||||
for expt in self.exports:
|
||||
print "Exporting: file %s, format %s." % expt
|
||||
# Need to convert path/filename to str before printing
|
||||
# For non latin characters in Windows path/file/user names
|
||||
fn = expt[0].encode(sys.getfilesystemencoding())
|
||||
fmt = str(expt[1])
|
||||
print "Exporting: file %s, format %s." % (fn, fmt)
|
||||
self.cl_export(expt[0], expt[1])
|
||||
|
||||
if cleanup:
|
||||
@@ -356,7 +369,11 @@ class ArgHandler(object):
|
||||
sys.exit(0)
|
||||
|
||||
for imp in self.imports:
|
||||
print "Importing: file %s, format %s." % imp
|
||||
# Need to covert path/filename to str before printing
|
||||
# For non latin characters in Windows path/file/user names
|
||||
fn = imp[0].encode(sys.getfilesystemencoding())
|
||||
fmt = str(imp[1])
|
||||
print "Importing: file %s, format %s." % (fn , fmt)
|
||||
self.cl_import(imp[0], imp[1])
|
||||
|
||||
def __open_action(self):
|
||||
@@ -480,9 +497,9 @@ class ArgHandler(object):
|
||||
if len(pdata.id) <= 25:
|
||||
print " %s%s- %s" % ( pdata.id,
|
||||
" " * (26 - len(pdata.id)),
|
||||
pdata.name)
|
||||
pdata.name.encode(sys.getfilesystemencoding()))
|
||||
else:
|
||||
print " %s\t- %s" % (pdata.id, pdata.name)
|
||||
print " %s\t- %s" % (pdata.id, pdata.name.encode(sys.getfilesystemencoding()) )
|
||||
|
||||
elif action == "tool":
|
||||
try:
|
||||
@@ -517,9 +534,9 @@ class ArgHandler(object):
|
||||
if len(pdata.id) <= 25:
|
||||
print " %s%s- %s" % ( pdata.id,
|
||||
" " * (26 - len(pdata.id)),
|
||||
pdata.name)
|
||||
pdata.name.encode(sys.getfilesystemencoding()))
|
||||
else:
|
||||
print " %s\t- %s" % (pdata.id, pdata.name)
|
||||
print " %s\t- %s" % (pdata.id, pdata.name.encode(sys.getfilesystemencoding()))
|
||||
else:
|
||||
print "Unknown action: %s." % action
|
||||
sys.exit(0)
|
||||
|
||||
+87
-5
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
@@ -44,6 +45,7 @@ import logging
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
import Utils
|
||||
|
||||
|
||||
# Note: Make sure to edit const.py POPT_TABLE too!
|
||||
@@ -68,6 +70,51 @@ Application options
|
||||
-u, --force-unlock Force unlock of family tree
|
||||
""")
|
||||
|
||||
_USAGE = _("""
|
||||
Example of usage of Gramps command line interface
|
||||
|
||||
1. To import four databases (whose formats can be determined from their names)
|
||||
and then check the resulting database for errors, one may type:
|
||||
gramps -i file1.ged -i file2.gpkg -i ~/db3.gramps -i file4.wft -a check
|
||||
|
||||
2. To explicitly specify the formats in the above example, append filenames with appropriate -f options:
|
||||
gramps -i file1.ged -f gedcom -i file2.gpkg -f gramps-pkg -i ~/db3.gramps -f gramps-xml -i file4.wft -f wft -a check
|
||||
|
||||
3. To record the database resulting from all imports, supply -e flag
|
||||
(use -f if the filename does not allow GRAMPS to guess the format):
|
||||
gramps -i file1.ged -i file2.gpkg -e ~/new-package -f gramps-pkg
|
||||
|
||||
4. To save any error messages of the above example into files outfile and errfile, run:
|
||||
gramps -i file1.ged -i file2.dpkg -e ~/new-package -f gramps-pkg >outfile 2>errfile
|
||||
|
||||
5. To import three databases and start interactive GRAMPS session with the result:
|
||||
gramps -i file1.ged -i file2.gpkg -i ~/db3.gramps
|
||||
|
||||
6. To open a database and, based on that data, generate timeline report in PDF format
|
||||
putting the output into the my_timeline.pdf file:
|
||||
gramps -O 'Family Tree 1' -a report -p name=timeline,off=pdf,of=my_timeline.pdf
|
||||
|
||||
7. To generate a summary of a database:
|
||||
gramps -O 'Family Tree 1' -a report -p name=summary
|
||||
|
||||
8. Listing report options
|
||||
Use the name=timeline,show=all to find out about all available options for the timeline report.
|
||||
To find out details of a particular option, use show=option_name , e.g. name=timeline,show=off string.
|
||||
To learn about available report names, use name=show string.
|
||||
|
||||
9. To convert a family tree on the fly to a .gramps xml file:
|
||||
gramps -O 'Family Tree 1' -e output.gramps -f gramps-xml
|
||||
|
||||
10. To generate a web site into an other locale (in german):
|
||||
LANGUAGE=de_DE; LANG=de_DE.UTF-8 gramps -O 'Family Tree 1' -a report -p name=navwebpage,target=/../de
|
||||
|
||||
11. Finally, to start normal interactive session type:
|
||||
gramps
|
||||
|
||||
Note: These examples are for bash shell.
|
||||
Syntax may be different for other shells and for Windows.
|
||||
""")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# ArgParser
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -121,6 +168,7 @@ class ArgParser(object):
|
||||
self.list = False
|
||||
self.list_more = False
|
||||
self.help = False
|
||||
self.usage = False
|
||||
self.force_unlock = False
|
||||
|
||||
self.errors = []
|
||||
@@ -150,14 +198,30 @@ class ArgParser(object):
|
||||
|
||||
"""
|
||||
try:
|
||||
# Convert arguments to unicode, otherwise getopt will not work
|
||||
# if a non latin character is used as an option (by mistake).
|
||||
# getopt will try to treat the first char in an utf-8 sequence. Example:
|
||||
# -Ärik is '-\xc3\x84rik' and getopt will respond :
|
||||
# option -\xc3 not recognized
|
||||
for arg in range(len(self.args) - 1):
|
||||
self.args[arg+1] = Utils.get_unicode_path_from_env_var(self.args[arg + 1])
|
||||
options, leftargs = getopt.getopt(self.args[1:],
|
||||
const.SHORTOPTS, const.LONGOPTS)
|
||||
except getopt.GetoptError, msg:
|
||||
# Extract the arguments in the list.
|
||||
# The % operator replaces the list elements with repr() of the list elemements
|
||||
# which is OK for latin characters, but not for non latin characters in list elements
|
||||
cliargs = "[ "
|
||||
for arg in range(len(self.args) - 1):
|
||||
cliargs += self.args[arg + 1] + " "
|
||||
cliargs += "]"
|
||||
# Must first do str() of the msg object.
|
||||
msg = unicode(str(msg))
|
||||
self.errors += [(_('Error parsing the arguments'),
|
||||
str(msg) + '\n' +
|
||||
msg + '\n' +
|
||||
_("Error parsing the arguments: %s \n"
|
||||
"Type gramps --help for an overview of commands, or "
|
||||
"read the manual pages.") % self.args[1:])]
|
||||
"read the manual pages.") % cliargs)]
|
||||
return
|
||||
|
||||
if leftargs:
|
||||
@@ -214,7 +278,9 @@ class ArgParser(object):
|
||||
self.help = True
|
||||
elif option in ('-u', '--force-unlock'):
|
||||
self.force_unlock = True
|
||||
|
||||
elif option in ('--usage'):
|
||||
self.usage = True
|
||||
|
||||
#clean options list
|
||||
cleandbg.reverse()
|
||||
for ind in cleandbg:
|
||||
@@ -222,10 +288,17 @@ class ArgParser(object):
|
||||
|
||||
if len(options) > 0 and self.open is None and self.imports == [] \
|
||||
and not (self.list or self.list_more or self.help):
|
||||
# Extract and convert to unicode the arguments in the list.
|
||||
# The % operator replaces the list elements with repr() of the list elemements
|
||||
# which is OK for latin characters, but not for non latin characters in list elements
|
||||
cliargs = "[ "
|
||||
for arg in range(len(self.args) - 1):
|
||||
cliargs += Utils.get_unicode_path_from_env_var(self.args[arg + 1]) + " "
|
||||
cliargs += "]"
|
||||
self.errors += [(_('Error parsing the arguments'),
|
||||
_("Error parsing the arguments: %s \n"
|
||||
"To use in the command-line mode," \
|
||||
"supply at least one input file to process.") % self.args[1:])]
|
||||
"supply at least one input file to process.") % cliargs)]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Determine the need for GUI
|
||||
@@ -262,6 +335,15 @@ class ArgParser(object):
|
||||
If the user gives the --help or -h option, print the output to terminal.
|
||||
"""
|
||||
if self.help:
|
||||
print _HELP
|
||||
# Convert Help messages to file system encoding before printing
|
||||
print _HELP.encode(sys.getfilesystemencoding())
|
||||
sys.exit(0)
|
||||
|
||||
def print_usage(self):
|
||||
"""
|
||||
If the user gives the --usage print the output to terminal.
|
||||
"""
|
||||
if self.usage:
|
||||
# Convert Help messages to file system encoding before printing
|
||||
print _USAGE.encode(sys.getfilesystemencoding())
|
||||
sys.exit(0)
|
||||
|
||||
+14
-4
@@ -297,14 +297,24 @@ def startcli(errors, argparser):
|
||||
"""
|
||||
if errors:
|
||||
#already errors encountered. Show first one on terminal and exit
|
||||
print _('Error encountered: %s') % errors[0][0]
|
||||
print _(' Details: %s') % errors[0][1]
|
||||
# Convert error message to file system encoding before print
|
||||
errmsg = _('Error encountered: %s') % errors[0][0]
|
||||
errmsg = errmsg.encode(sys.getfilesystemencoding())
|
||||
print errmsg
|
||||
errmsg = _(' Details: %s') % errors[0][1]
|
||||
errmsg = errmsg.encode(sys.getfilesystemencoding())
|
||||
print errmsg
|
||||
sys.exit(1)
|
||||
|
||||
if argparser.errors:
|
||||
print _('Error encountered in argument parsing: %s') \
|
||||
# Convert error message to file system encoding before print
|
||||
errmsg = _('Error encountered in argument parsing: %s') \
|
||||
% argparser.errors[0][0]
|
||||
print _(' Details: %s') % argparser.errors[0][1]
|
||||
errmsg = errmsg.encode(sys.getfilesystemencoding())
|
||||
print errmsg
|
||||
errmsg = _(' Details: %s') % argparser.errors[0][1]
|
||||
errmsg = errmsg.encode(sys.getfilesystemencoding())
|
||||
print errmsg
|
||||
sys.exit(1)
|
||||
|
||||
#we need to keep track of the db state
|
||||
|
||||
+2
-2
@@ -42,10 +42,10 @@ from gettext import gettext as _
|
||||
#-------------------------------------------------------------------------
|
||||
PROGRAM_NAME = "Gramps"
|
||||
if "@VERSIONSTRING@" == "@" + "VERSIONSTRING" + "@":
|
||||
VERSION = "3.2.4"
|
||||
VERSION = "3.2.5"
|
||||
else:
|
||||
VERSION = "@VERSIONSTRING@"
|
||||
VERSION_TUPLE = (3, 2, 4)
|
||||
VERSION_TUPLE = (3, 2, 5)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
@@ -6,6 +6,7 @@ SUBDIRS =
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/data
|
||||
|
||||
dist_pkgdata_DATA = \
|
||||
ancestortree.css \
|
||||
authors.xml \
|
||||
gedcom.xml \
|
||||
papersize.xml \
|
||||
|
||||
@@ -826,6 +826,9 @@ div#addresses table.infolist tbody tr td.ColumnValue {
|
||||
border:solid 1px #999;
|
||||
}
|
||||
#indivgallery div.thumbnail p {
|
||||
/* ## remove this line and the comment markers from the line below to hide the description in Individual Gallery
|
||||
display: none; */
|
||||
|
||||
font-size:.6em;
|
||||
text-align:center;
|
||||
width:80%;
|
||||
|
||||
@@ -1119,6 +1119,9 @@ div#Residence table.infolist tr td {
|
||||
border: solid 1px #000;
|
||||
}
|
||||
#indivgallery div.thumbnail p {
|
||||
/* ## remove this line and the comment markers from the line below to hide the description in Individual Gallery
|
||||
display: none; */
|
||||
|
||||
font:normal .7em/1.4em sans-serif;
|
||||
text-align:center;
|
||||
width:80%;
|
||||
|
||||
@@ -823,6 +823,9 @@ div#addresses table.infolist tbody tr td.ColumnValue {
|
||||
border:solid 1px #7C8F7C;
|
||||
}
|
||||
#indivgallery div.thumbnail p {
|
||||
/* ## remove this line and the comment markers from the line below to hide the description in Individual Gallery
|
||||
display: none; */
|
||||
|
||||
font-size:.6em;
|
||||
text-align:center;
|
||||
width:80%;
|
||||
|
||||
@@ -824,6 +824,9 @@ div#addresses table.infolist tbody tr td.ColumnValue {
|
||||
border:solid 1px #669;
|
||||
}
|
||||
#indivgallery div.thumbnail p {
|
||||
/* ## remove this line and the comment markers from the line below to hide the description in Individual Gallery
|
||||
display: none; */
|
||||
|
||||
font-size:.6em;
|
||||
text-align:center;
|
||||
width:80%;
|
||||
|
||||
@@ -825,6 +825,9 @@ div#addresses table.infolist tbody tr td.ColumnValue {
|
||||
border:solid 1px #8C581C;
|
||||
}
|
||||
#indivgallery div.thumbnail p {
|
||||
/* ## remove this line and the comment markers from the line below to hide the description in Individual Gallery
|
||||
display: none; */
|
||||
|
||||
font-size:.6em;
|
||||
text-align:center;
|
||||
width:80%;
|
||||
|
||||
@@ -825,6 +825,9 @@ div#addresses table.infolist tbody tr td.ColumnValue {
|
||||
border:solid 1px #7CA3DD;
|
||||
}
|
||||
#indivgallery div.thumbnail p {
|
||||
/* ## remove this line and the comment markers from the line below to hide the description in Individual Gallery
|
||||
display: none; */
|
||||
|
||||
font-size:.6em;
|
||||
text-align:center;
|
||||
width:80%;
|
||||
|
||||
@@ -830,6 +830,9 @@ div#addresses table.infolist tbody tr td.ColumnValue {
|
||||
border:solid 1px #7D5925;
|
||||
}
|
||||
#indivgallery div.thumbnail p {
|
||||
/* ## remove this line and the comment markers from the line below to hide the description in Individual Gallery
|
||||
display: none; */
|
||||
|
||||
font-size:.6em;
|
||||
text-align:center;
|
||||
width:80%;
|
||||
|
||||
@@ -846,6 +846,9 @@ div#addresses table.infolist tbody tr td.ColumnValue {
|
||||
border:solid 1px #542;
|
||||
}
|
||||
#indivgallery div.thumbnail p {
|
||||
/* ## remove this line and the comment markers from the line below to hide the description in Individual Gallery
|
||||
display: none; */
|
||||
|
||||
font:normal .7em/1.4em sans-serif;
|
||||
text-align:center;
|
||||
width:80%;
|
||||
|
||||
@@ -951,6 +951,9 @@ div#addresses table.infolist tbody tr td.ColumnValue {
|
||||
border:solid 1px #453619;
|
||||
}
|
||||
#indivgallery div.thumbnail p {
|
||||
/* ## remove this line and the comment markers from the line below to hide the description in Individual Gallery
|
||||
display: none; */
|
||||
|
||||
font:normal .7em/1.4em sans-serif;
|
||||
text-align:center;
|
||||
width:80%;
|
||||
|
||||
+21
-3
@@ -92,6 +92,9 @@ class DbBookmarks(object):
|
||||
def insert(self, pos, item):
|
||||
self.bookmarks.insert(pos, item)
|
||||
|
||||
def close(self):
|
||||
del self.bookmarks
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GrampsDBReadCursor
|
||||
@@ -169,7 +172,6 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
Create a new DbBsddbRead instance.
|
||||
"""
|
||||
|
||||
DbReadBase.__init__(self)
|
||||
Callback.__init__(self)
|
||||
|
||||
@@ -379,8 +381,24 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
|
||||
The method needs to be overridden in the derived class.
|
||||
"""
|
||||
pass
|
||||
|
||||
#remove links to functions
|
||||
self.disconnect_all()
|
||||
for key in self._tables:
|
||||
for subkey in self._tables[key]:
|
||||
self._tables[key][subkey] = None
|
||||
del self._tables[key][subkey]
|
||||
self._tables[key] = None
|
||||
del self._tables
|
||||
## self.bookmarks = None
|
||||
## self.family_bookmarks = None
|
||||
## self.event_bookmarks = None
|
||||
## self.place_bookmarks = None
|
||||
## self.source_bookmarks = None
|
||||
## self.repo_bookmarks = None
|
||||
## self.media_bookmarks = None
|
||||
## self.note_bookmarks = None
|
||||
|
||||
|
||||
def is_open(self):
|
||||
"""
|
||||
Return 1 if the database has been opened.
|
||||
|
||||
@@ -414,6 +414,10 @@ class DbUndoBSDDB(DbUndo):
|
||||
Close the undo/redo database
|
||||
"""
|
||||
self.undodb.close()
|
||||
self.undodb = None
|
||||
self.mapbase = None
|
||||
self.db = None
|
||||
|
||||
try:
|
||||
os.remove(self.path)
|
||||
except OSError:
|
||||
|
||||
+18
-1
@@ -1000,7 +1000,6 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
def close(self):
|
||||
if not self.db_is_open:
|
||||
return
|
||||
|
||||
self.env.txn_checkpoint()
|
||||
|
||||
self.__close_metadata()
|
||||
@@ -1045,6 +1044,24 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.env = None
|
||||
self.metadata = None
|
||||
self.db_is_open = False
|
||||
|
||||
DbBsddbRead.close(self)
|
||||
|
||||
self.person_map = None
|
||||
self.family_map = None
|
||||
self.repository_map = None
|
||||
self.note_map = None
|
||||
self.place_map = None
|
||||
self.source_map = None
|
||||
self.media_map = None
|
||||
self.event_map = None
|
||||
self.reference_map_primary_map = None
|
||||
self.reference_map_referenced_map = None
|
||||
self.reference_map = None
|
||||
self.undo_callback = None
|
||||
self.redo_callback = None
|
||||
self.undo_history_callback = None
|
||||
self.undodb = None
|
||||
|
||||
try:
|
||||
clear_lock_file(self.get_save_path())
|
||||
|
||||
+5
-1
@@ -41,6 +41,10 @@ def gettext(msgid):
|
||||
:returns: Translation or the original.
|
||||
:rtype: unicode
|
||||
"""
|
||||
# If msgid =="" then gettext will return po file header
|
||||
# and that's not what we want.
|
||||
if len(msgid.strip()) == 0:
|
||||
return msgid
|
||||
return unicode(pgettext.gettext(msgid))
|
||||
|
||||
def ngettext(singular, plural, n):
|
||||
@@ -82,4 +86,4 @@ def sgettext(msgid, sep='|'):
|
||||
if msgval == msgid:
|
||||
sep_idx = msgid.rfind(sep)
|
||||
msgval = msgid[sep_idx+1:]
|
||||
return unicode(msgval)
|
||||
return unicode(msgval)
|
||||
|
||||
@@ -628,56 +628,56 @@ class ProxyDbBase(DbReadBase):
|
||||
Returns True if the handle exists in the current Person database.
|
||||
"""
|
||||
return self.gfilter(self.include_person,
|
||||
self.db.get_person_from_gramps_id(val)) is not None
|
||||
self.db.get_person_from_handle(handle)) is not None
|
||||
|
||||
def has_family_handle(self, handle):
|
||||
"""
|
||||
Returns True if the handle exists in the current Family database.
|
||||
"""
|
||||
return self.gfilter(self.include_family,
|
||||
self.db.get_family_from_gramps_id(val)) is not None
|
||||
self.db.get_family_from_handle(handle)) is not None
|
||||
|
||||
def has_event_handle(self, handle):
|
||||
"""
|
||||
returns True if the handle exists in the current Event database.
|
||||
"""
|
||||
return self.gfilter(self.include_event,
|
||||
self.db.get_event_from_gramps_id(val)) is not None
|
||||
self.db.get_event_from_handle(handle)) is not None
|
||||
|
||||
def has_source_handle(self, handle):
|
||||
"""
|
||||
returns True if the handle exists in the current Source database.
|
||||
"""
|
||||
return self.gfilter(self.include_source,
|
||||
self.db.get_source_from_gramps_id(val)) is not None
|
||||
self.db.get_source_from_handle(handle)) is not None
|
||||
|
||||
def has_place_handle(self, handle):
|
||||
"""
|
||||
returns True if the handle exists in the current Place database.
|
||||
"""
|
||||
return self.gfilter(self.include_place,
|
||||
self.db.get_place_from_gramps_id(val)) is not None
|
||||
self.db.get_place_from_handle(handle)) is not None
|
||||
|
||||
def has_object_handle(self, handle):
|
||||
"""
|
||||
returns True if the handle exists in the current MediaObjectdatabase.
|
||||
"""
|
||||
return self.gfilter(self.include_media_object,
|
||||
self.db.get_object_from_gramps_id(val)) is not None
|
||||
self.db.get_object_from_handle(handle)) is not None
|
||||
|
||||
def has_repository_handle(self, handle):
|
||||
"""
|
||||
returns True if the handle exists in the current Repository database.
|
||||
"""
|
||||
return self.gfilter(self.include_repository,
|
||||
self.db.get_repository_from_gramps_id(val)) is not None
|
||||
self.db.get_repository_from_handle(handle)) is not None
|
||||
|
||||
def has_note_handle(self, handle):
|
||||
"""
|
||||
returns True if the handle exists in the current Note database.
|
||||
"""
|
||||
return self.gfilter(self.include_note,
|
||||
self.db.get_note_from_gramps_id(val)) is not None
|
||||
self.db.get_note_from_handle(handle)) is not None
|
||||
|
||||
def get_mediapath(self):
|
||||
"""returns the default media path of the database"""
|
||||
|
||||
@@ -40,6 +40,7 @@ import sys
|
||||
import types
|
||||
import traceback
|
||||
import inspect
|
||||
import copy
|
||||
|
||||
log = sys.stderr.write
|
||||
|
||||
@@ -311,8 +312,16 @@ class Callback(object):
|
||||
": %s with key: %s\n" % (signal_name,
|
||||
str(key)))
|
||||
self.__callback_map[signal_name].remove(cb)
|
||||
|
||||
|
||||
|
||||
def disconnect_all(self):# Find the key in the callback map.
|
||||
for signal_name in self.__callback_map:
|
||||
keymap = copy.copy(self.__callback_map[signal_name])
|
||||
for key in keymap:
|
||||
self.__callback_map[signal_name].remove(key)
|
||||
self.__callback_map[signal_name] = None
|
||||
self.__callback_map = None
|
||||
del self.__callback_map
|
||||
|
||||
def emit(self, signal_name, args=tuple()):
|
||||
"""
|
||||
Emit the signal called signal_name. The args must be a tuple of
|
||||
|
||||
@@ -38,14 +38,18 @@ import ConfigParser
|
||||
import errno
|
||||
import copy
|
||||
|
||||
try:
|
||||
from ast import literal_eval as safe_eval
|
||||
except:
|
||||
# PYTHON2.5 COMPATIBILITY: no ast present
|
||||
# not as safe as literal_eval, but works for python2.5:
|
||||
def safe_eval(exp):
|
||||
def safe_eval(exp):
|
||||
# restrict eval to empty environment
|
||||
return eval(exp, {})
|
||||
##try:
|
||||
## from ast import literal_eval as safe_eval
|
||||
## # this leaks memory !!
|
||||
##except:
|
||||
## # PYTHON2.5 COMPATIBILITY: no ast present
|
||||
## # not as safe as literal_eval, but works for python2.5:
|
||||
## def safe_eval(exp):
|
||||
## # restrict eval to empty environment
|
||||
## return eval(exp, {})
|
||||
|
||||
#---------------------------------------------------------------
|
||||
#
|
||||
|
||||
@@ -181,6 +181,7 @@ def run():
|
||||
else:
|
||||
#CLI use of GRAMPS
|
||||
argpars.print_help()
|
||||
argpars.print_usage()
|
||||
from cli.grampscli import startcli
|
||||
startcli(error, argpars)
|
||||
|
||||
|
||||
+2
-10
@@ -86,14 +86,7 @@ class DbLoader(CLIDbLoader):
|
||||
return 1
|
||||
|
||||
def _dberrordialog(self, msg):
|
||||
import traceback
|
||||
exc = traceback.format_exc()
|
||||
try:
|
||||
DBErrorDialog(str(msg.value))
|
||||
_LOG.error(str(msg.value))
|
||||
except:
|
||||
DBErrorDialog(str(msg))
|
||||
_LOG.error(str(msg) +"\n" + exc)
|
||||
DBErrorDialog(str(msg.value))
|
||||
|
||||
def _begin_progress(self):
|
||||
self.uistate.set_busy_cursor(1)
|
||||
@@ -319,9 +312,8 @@ class DbLoader(CLIDbLoader):
|
||||
except Errors.DbError, msg:
|
||||
self.dbstate.no_database()
|
||||
self._dberrordialog(msg)
|
||||
except Exception as newerror:
|
||||
except Exception:
|
||||
self.dbstate.no_database()
|
||||
self._dberrordialog(str(newerror))
|
||||
self._end_progress()
|
||||
return True
|
||||
|
||||
|
||||
+31
-1
@@ -68,7 +68,7 @@ import pango
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from QuestionDialog import ErrorDialog, QuestionDialog
|
||||
from QuestionDialog import ErrorDialog, QuestionDialog, QuestionDialog2
|
||||
from gen.db import DbBsddb
|
||||
from gui.pluginmanager import GuiPluginManager
|
||||
from cli.clidbman import CLIDbManager, NAME_FILE, time_val
|
||||
@@ -627,6 +627,36 @@ class DbManager(CLIDbManager):
|
||||
"""
|
||||
store, node = self.selection.get_selected()
|
||||
dirname = store[node][1]
|
||||
|
||||
#First ask user if he is really sure :-)
|
||||
yes_no = QuestionDialog2(
|
||||
_("Repair family tree?"),
|
||||
_(
|
||||
"If you click <b>Proceed</b>, Gramps will attempt to recover your family tree"
|
||||
" from the last good backup. There are several ways this can cause unwanted"
|
||||
" effects, so <b>backup</b> the family tree first.\n"
|
||||
"The Family tree you have selected is stored in %s.\n\n"
|
||||
"Before doing a repair, verify that the Family Tree can really no longer be "
|
||||
" opened, as the database back-end can recover from some errors automatically.\n\n"
|
||||
"<b>Details:</b> Repairing a Family Tree actually uses the last backup of"
|
||||
" the Family Tree, which Gramps stored on last use. If you have worked for"
|
||||
" several hours/days without closing Gramps, then all this information will"
|
||||
" be lost! If the repair fails, then the original family tree will be lost"
|
||||
" forever, hence a backup is needed. If the repair fails, or too much"
|
||||
" information is lost, you can fix the original family tree manually."
|
||||
" For details, see the webpage\n"
|
||||
"http://gramps-project.org/wiki/index.php?title=Recover_corrupted_family_tree\n"
|
||||
"Before doing a repair, try to open the family tree in the normal manner."
|
||||
" Several errors that trigger the repair button can be fixed automatically."
|
||||
" If this is the case, you can disable the repair button by removing the"
|
||||
" file <i>need_recover</i> in the family tree directory."
|
||||
) % dirname,
|
||||
_("Proceed, I have taken a backup"),
|
||||
_("Stop"))
|
||||
prompt = yes_no.run()
|
||||
if not prompt:
|
||||
return
|
||||
|
||||
opened = store[node][5]
|
||||
if opened:
|
||||
self.dbstate.no_database()
|
||||
|
||||
@@ -66,7 +66,7 @@ class BackRefList(EmbeddedList):
|
||||
EmbeddedList.__init__(self, dbstate, uistate, track,
|
||||
_('_References'), refmodel)
|
||||
self._callback = callback
|
||||
self.model.connect('row-inserted', self.update_label)
|
||||
self.connectid = self.model.connect('row-inserted', self.update_label)
|
||||
self.track_ref_for_deletion("model")
|
||||
|
||||
def update_label(self, *obj):
|
||||
@@ -78,8 +78,13 @@ class BackRefList(EmbeddedList):
|
||||
def right_click(self, obj, event):
|
||||
return
|
||||
|
||||
def close(self):
|
||||
self.model.close()
|
||||
def _cleanup_local_connects(self):
|
||||
self.model.disconnect(self.connectid)
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
# model may be destroyed already in closing managedwindow
|
||||
if hasattr(self, 'model'):
|
||||
self.model.destroy()
|
||||
|
||||
def is_empty(self):
|
||||
return self.model.count == 0
|
||||
|
||||
@@ -54,10 +54,18 @@ class BackRefModel(gtk.ListStore):
|
||||
self.count = 0
|
||||
self.idle = gobject.idle_add(self.load_model().next)
|
||||
|
||||
def close(self):
|
||||
def destroy(self):
|
||||
gobject.source_remove(self.idle)
|
||||
|
||||
def load_model(self):
|
||||
"""
|
||||
Objects can have very large backreferences. To avoid blocking the
|
||||
interface up to the moment that the model is created, this method is
|
||||
called via gobject.idle_add.
|
||||
WARNING: a consequence of above is that loading can still be happening
|
||||
while the GUI using this model is no longer used. Disconnect any
|
||||
methods before closing the GUI.
|
||||
"""
|
||||
self.count = 0
|
||||
for ref in self.sref_list:
|
||||
self.count += 1
|
||||
|
||||
@@ -69,6 +69,7 @@ class EmbeddedList(ButtonTab):
|
||||
move_buttons, jump_button)
|
||||
|
||||
self.changed = False
|
||||
self.model = None
|
||||
self.build_model = build_model
|
||||
|
||||
# handle the selection
|
||||
@@ -466,6 +467,9 @@ class EmbeddedList(ButtonTab):
|
||||
selectedpath = None
|
||||
if node:
|
||||
selectedpath = model.get_path(node)
|
||||
if self.model and hasattr(self.model, 'destroy'):
|
||||
self.tree.set_model(None)
|
||||
self.model.destroy()
|
||||
try:
|
||||
self.model = self.construct_model()
|
||||
except AttributeError, msg:
|
||||
|
||||
@@ -78,6 +78,8 @@ class NameEmbedList(GroupEmbeddedList):
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data, person, callback):
|
||||
"""callback is the function to call when preferred name changes
|
||||
on the namelist """
|
||||
self.data = data
|
||||
self.person = person
|
||||
self.callback = callback
|
||||
@@ -86,6 +88,14 @@ class NameEmbedList(GroupEmbeddedList):
|
||||
NameModel, move_buttons=True)
|
||||
self.tree.expand_all()
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
"""Unset all things that can block garbage collection.
|
||||
Finalize rest
|
||||
"""
|
||||
self.person = None
|
||||
self.callback = None
|
||||
self.data = None
|
||||
|
||||
def get_data(self):
|
||||
return ([self.person.get_primary_name()],
|
||||
self.data)
|
||||
|
||||
@@ -129,15 +129,15 @@ class EditAddress(EditSecondary):
|
||||
|
||||
notebook = gtk.Notebook()
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
|
||||
self.srcref_list = SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj)
|
||||
self._add_tab(notebook, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.note_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=NoteType.ADDRESS))
|
||||
notetype=NoteType.ADDRESS)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
notebook.show_all()
|
||||
|
||||
@@ -107,15 +107,15 @@ class EditAttribute(EditSecondary):
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
notebook = gtk.Notebook()
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
|
||||
self.srcref_list = SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj)
|
||||
self._add_tab(notebook, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.note_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype = NoteType.ATTRIBUTE))
|
||||
notetype = NoteType.ATTRIBUTE)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
notebook.show_all()
|
||||
|
||||
@@ -144,15 +144,15 @@ class EditChildRef(EditSecondary):
|
||||
"""
|
||||
notebook = gtk.Notebook()
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
|
||||
self.srcref_list = SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj)
|
||||
self._add_tab(notebook, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.note_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=NoteType.CHILDREF))
|
||||
notetype=NoteType.CHILDREF)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
notebook.show_all()
|
||||
|
||||
@@ -213,9 +213,6 @@ class EditEvent(EditPrimary):
|
||||
self.track_ref_for_deletion("attr_list")
|
||||
self.track_ref_for_deletion("backref_list")
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
self.backref_list.close()
|
||||
|
||||
def build_menu_names(self, event):
|
||||
return (_('Edit Event'), self.get_menu_title())
|
||||
|
||||
|
||||
@@ -425,6 +425,15 @@ class EditFamily(EditPrimary):
|
||||
else:
|
||||
self.add_parent = False
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
"""Unset all things that can block garbage collection.
|
||||
Finalize rest
|
||||
"""
|
||||
#FIXME, we rebind show_all below, this prevents garbage collection of
|
||||
# the dialog, fix the rebind
|
||||
self.window.show_all = None
|
||||
EditPrimary._cleanup_on_exit(self)
|
||||
|
||||
def empty_object(self):
|
||||
return gen.lib.Family()
|
||||
|
||||
|
||||
@@ -198,6 +198,7 @@ class EditLdsOrd(EditSecondary):
|
||||
if item[0] in self._get_types()],
|
||||
self.db.readonly,
|
||||
changed=self.ord_type_changed)
|
||||
self.track_ref_for_deletion('type_menu')
|
||||
|
||||
self.temple_menu = MonitoredStrMenu(
|
||||
self.top.get_object('temple'),
|
||||
@@ -205,6 +206,7 @@ class EditLdsOrd(EditSecondary):
|
||||
self.obj.get_temple,
|
||||
LdsUtils.TEMPLES.name_code_data(),
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion('temple_menu')
|
||||
|
||||
self.status_menu = MonitoredMenu(
|
||||
self.top.get_object('status'),
|
||||
@@ -213,6 +215,7 @@ class EditLdsOrd(EditSecondary):
|
||||
[(item[1],item[0]) for item in gen.lib.LdsOrd._STATUS_MAP
|
||||
if item[0] in _DATA_MAP[self.obj.get_type()] ],
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion('status_menu')
|
||||
|
||||
self.ord_type_changed()
|
||||
self.update_parent_label()
|
||||
@@ -236,15 +239,16 @@ class EditLdsOrd(EditSecondary):
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
notebook = gtk.Notebook()
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate, self.track,self.obj))
|
||||
self.srcref_list = SourceEmbedList(self.dbstate, self.uistate,
|
||||
self.track, self.obj)
|
||||
self._add_tab(notebook, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.note_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=gen.lib.NoteType.LDS))
|
||||
notetype=gen.lib.NoteType.LDS)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
notebook.show_all()
|
||||
@@ -304,6 +308,7 @@ class EditLdsOrd(EditSecondary):
|
||||
"""
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.callback = None
|
||||
self.close()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -378,6 +383,7 @@ class EditFamilyLdsOrd(EditSecondary):
|
||||
[(item[1],item[0]) for item in gen.lib.LdsOrd._TYPE_MAP
|
||||
if item[0] in self._get_types()],
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion('type_menu')
|
||||
|
||||
self.temple_menu = MonitoredStrMenu(
|
||||
self.top.get_object('temple'),
|
||||
@@ -385,6 +391,7 @@ class EditFamilyLdsOrd(EditSecondary):
|
||||
self.obj.get_temple,
|
||||
LdsUtils.TEMPLES.name_code_data(),
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion('temple_menu')
|
||||
|
||||
self.status_menu = MonitoredMenu(
|
||||
self.top.get_object('status'),
|
||||
@@ -393,18 +400,19 @@ class EditFamilyLdsOrd(EditSecondary):
|
||||
[(item[1],item[0]) for item in gen.lib.LdsOrd._STATUS_MAP
|
||||
if item[0] in _DATA_MAP[self.obj.get_type()]],
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion('status_menu')
|
||||
|
||||
def _create_tabbed_pages(self):
|
||||
notebook = gtk.Notebook()
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate, self.track,self.obj))
|
||||
self.srcref_list = SourceEmbedList(self.dbstate,self.uistate, self.track,self.obj)
|
||||
self._add_tab(notebook, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.note_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=gen.lib.NoteType.LDS))
|
||||
notetype=gen.lib.NoteType.LDS)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
notebook.show_all()
|
||||
self.top.get_object('vbox').pack_start(notebook,True)
|
||||
|
||||
@@ -293,9 +293,6 @@ class EditMedia(EditPrimary):
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
self.backref_list.close()
|
||||
|
||||
def data_has_changed(self):
|
||||
"""
|
||||
A date comparison can fail incorrectly because we have made the
|
||||
|
||||
@@ -82,17 +82,21 @@ class EditMediaRef(EditReference):
|
||||
self.top.get_object("label428").set_text(_("Y coordinate|Y"))
|
||||
|
||||
tblref = self.top.get_object('table50')
|
||||
notebook = self.top.get_object('notebook_ref')
|
||||
self.notebook_ref = self.top.get_object('notebook_ref')
|
||||
self.track_ref_for_deletion("notebook_ref")
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.notebook_ref.remove_page(0)
|
||||
self.reftab = RefTab(self.dbstate, self.uistate, self.track,
|
||||
_('General'), tblref)
|
||||
self.track_ref_for_deletion("reftab")
|
||||
tblref = self.top.get_object('table2')
|
||||
notebook = self.top.get_object('notebook_shared')
|
||||
self.notebook_shared = self.top.get_object('notebook_shared')
|
||||
#recreate start page as GrampsTab
|
||||
notebook.remove_page(0)
|
||||
self.notebook_shared.remove_page(0)
|
||||
self.track_ref_for_deletion("notebook_shared")
|
||||
self.primtab = RefTab(self.dbstate, self.uistate, self.track,
|
||||
_('_General'), tblref)
|
||||
self.track_ref_for_deletion("primtab")
|
||||
|
||||
def draw_preview(self):
|
||||
"""
|
||||
@@ -140,6 +144,7 @@ class EditMediaRef(EditReference):
|
||||
|
||||
self.rectangle = coord
|
||||
self.subpixmap = self.top.get_object("subpixmap")
|
||||
self.track_ref_for_deletion("subpixmap")
|
||||
|
||||
self.draw_preview()
|
||||
|
||||
@@ -161,24 +166,28 @@ class EditMediaRef(EditReference):
|
||||
self.set_corner1_x,
|
||||
self.get_corner1_x,
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion("corner1_x_spinbutton")
|
||||
|
||||
self.corner1_y_spinbutton = MonitoredSpinButton(
|
||||
self.top.get_object("corner1_y"),
|
||||
self.set_corner1_y,
|
||||
self.get_corner1_y,
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion("corner1_y_spinbutton")
|
||||
|
||||
self.corner2_x_spinbutton = MonitoredSpinButton(
|
||||
self.top.get_object("corner2_x"),
|
||||
self.set_corner2_x,
|
||||
self.get_corner2_x,
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion("corner2_x_spinbutton")
|
||||
|
||||
self.corner2_y_spinbutton = MonitoredSpinButton(
|
||||
self.top.get_object("corner2_y"),
|
||||
self.set_corner2_y,
|
||||
self.get_corner2_y,
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion("corner2_y_spinbutton")
|
||||
|
||||
self.descr_window = MonitoredEntry(
|
||||
self.top.get_object("description"),
|
||||
@@ -493,44 +502,44 @@ class EditMediaRef(EditReference):
|
||||
self._add_tab(notebook_src, self.primtab)
|
||||
self._add_tab(notebook_ref, self.reftab)
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook_ref,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source_ref))
|
||||
self.srcref_list = SourceEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source_ref)
|
||||
self._add_tab(notebook_ref, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.attr_list = self._add_tab(
|
||||
notebook_ref,
|
||||
AttrEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source_ref.get_attribute_list()))
|
||||
self.attr_list = AttrEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source_ref.get_attribute_list())
|
||||
self._add_tab(notebook_ref, self.attr_list)
|
||||
self.track_ref_for_deletion("attr_list")
|
||||
|
||||
self.backref_list = self._add_tab(
|
||||
notebook_src,
|
||||
MediaBackRefList(self.dbstate,self.uistate,self.track,
|
||||
self.backref_list = MediaBackRefList(self.dbstate,self.uistate,self.track,
|
||||
self.db.find_backlink_handles(self.source.handle),
|
||||
self.enable_warnbox
|
||||
))
|
||||
)
|
||||
self._add_tab(notebook_src, self.backref_list)
|
||||
self.track_ref_for_deletion("backref_list")
|
||||
|
||||
self.note_ref_tab = self._add_tab(
|
||||
notebook_ref,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source_ref.get_note_list(),
|
||||
notetype=NoteType.MEDIAREF))
|
||||
self.note_ref_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source_ref.get_note_list(),
|
||||
notetype=NoteType.MEDIAREF)
|
||||
self._add_tab(notebook_ref, self.note_ref_tab)
|
||||
self.track_ref_for_deletion("note_ref_tab")
|
||||
|
||||
self.src_srcref_list = self._add_tab(
|
||||
notebook_src,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source))
|
||||
self.src_srcref_list = SourceEmbedList(self.dbstate,self.uistate,
|
||||
self.track, self.source)
|
||||
self._add_tab(notebook_src, self.src_srcref_list)
|
||||
self.track_ref_for_deletion("src_srcref_list")
|
||||
|
||||
self.src_attr_list = self._add_tab(
|
||||
notebook_src,
|
||||
AttrEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source.get_attribute_list()))
|
||||
self.src_attr_list = AttrEmbedList(self.dbstate,self.uistate,self.track,
|
||||
self.source.get_attribute_list())
|
||||
self._add_tab(notebook_src, self.src_attr_list)
|
||||
self.track_ref_for_deletion("src_attr_list")
|
||||
|
||||
self.src_note_ref_tab = self._add_tab(
|
||||
notebook_src,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_note_list(),
|
||||
notetype=NoteType.MEDIA))
|
||||
self.src_note_ref_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_note_list(),
|
||||
notetype=NoteType.MEDIA)
|
||||
self._add_tab(notebook_src, self.src_note_ref_tab)
|
||||
self.track_ref_for_deletion("src_note_ref_tab")
|
||||
|
||||
self._setup_notebook_tabs(notebook_src)
|
||||
self._setup_notebook_tabs(notebook_ref)
|
||||
@@ -569,5 +578,5 @@ class EditMediaRef(EditReference):
|
||||
#call callback if given
|
||||
if self.update:
|
||||
self.update(self.source_ref,self.source)
|
||||
|
||||
self.update = None
|
||||
self.close()
|
||||
|
||||
@@ -35,6 +35,7 @@ from gen.ggettext import gettext as _
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gobject
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -171,6 +172,7 @@ class EditName(EditSecondary):
|
||||
self.obj.get_sort_as,
|
||||
format_list,
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion("sort_as")
|
||||
|
||||
self.display_as = MonitoredMenu(
|
||||
self.top.get_object('display_as'),
|
||||
@@ -178,6 +180,7 @@ class EditName(EditSecondary):
|
||||
self.obj.get_display_as,
|
||||
format_list,
|
||||
self.db.readonly)
|
||||
self.track_ref_for_deletion("display_as")
|
||||
|
||||
self.given_field = MonitoredEntry(
|
||||
self.top.get_object("alt_given"),
|
||||
@@ -248,16 +251,17 @@ class EditName(EditSecondary):
|
||||
notebook = self.top.get_object("notebook")
|
||||
|
||||
self._add_tab(notebook, self.gennam)
|
||||
self.track_ref_for_deletion("gennam")
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
|
||||
self.srcref_list = SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj)
|
||||
self._add_tab(notebook, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.note_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=NoteType.PERSONNAME))
|
||||
notetype=NoteType.PERSONNAME)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
|
||||
@@ -423,6 +427,7 @@ class EditName(EditSecondary):
|
||||
if closeit:
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.callback = None
|
||||
self.close()
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
@@ -436,3 +441,4 @@ class EditName(EditSecondary):
|
||||
# can't use group_over, see Note in gen/lib/name/Name.set_group_as().
|
||||
if not self.group_as.obj.get_editable():
|
||||
self.obj.set_group_as("")
|
||||
EditSecondary._cleanup_on_exit(self)
|
||||
|
||||
@@ -754,6 +754,7 @@ class EditPerson(EditPrimary):
|
||||
self.close()
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.callback = None
|
||||
|
||||
def _edit_name_clicked(self, obj):
|
||||
"""
|
||||
@@ -763,8 +764,11 @@ class EditPerson(EditPrimary):
|
||||
on the main form (not in the names tab).
|
||||
|
||||
"""
|
||||
EditName(self.dbstate, self.uistate, self.track,
|
||||
try:
|
||||
EditName(self.dbstate, self.uistate, self.track,
|
||||
self.pname, self._update_name)
|
||||
except Errors.WindowActiveError:
|
||||
pass
|
||||
|
||||
def _update_name(self, name):
|
||||
"""
|
||||
@@ -886,10 +890,14 @@ class EditPerson(EditPrimary):
|
||||
return child_ref_list
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
"""Unset all things that can block garbage collection.
|
||||
Finalize rest
|
||||
"""
|
||||
config.set('interface.prefix-suffix', self.prefix_suffix.active_key)
|
||||
config.set('interface.patro-title', self.patro_title.active_key)
|
||||
config.save()
|
||||
|
||||
EditPrimary._cleanup_on_exit(self)
|
||||
|
||||
class GenderDialog(gtk.MessageDialog):
|
||||
def __init__(self, parent=None):
|
||||
|
||||
@@ -141,19 +141,20 @@ class EditPersonRef(EditSecondary):
|
||||
|
||||
notebook = gtk.Notebook()
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook,
|
||||
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=NoteType.ASSOCIATION))
|
||||
self.srcref_list = SourceEmbedList(self.dbstate, self.uistate,
|
||||
self.track, self.obj)
|
||||
self._add_tab(notebook, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self._setup_notebook_tabs( notebook)
|
||||
self.note_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_note_list(),
|
||||
notetype=NoteType.ASSOCIATION)
|
||||
self._add_tab(notebook, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self._setup_notebook_tabs(notebook)
|
||||
notebook.show_all()
|
||||
self.top.get_object('vbox').pack_start(notebook,True)
|
||||
self.top.get_object('vbox').pack_start(notebook, True)
|
||||
|
||||
def build_menu_names(self, obj):
|
||||
return (_('Person Reference'),_('Person Reference Editor'))
|
||||
@@ -167,6 +168,7 @@ class EditPersonRef(EditSecondary):
|
||||
if self.obj.ref:
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.callback = None
|
||||
self.close()
|
||||
else:
|
||||
from QuestionDialog import ErrorDialog
|
||||
|
||||
@@ -278,9 +278,6 @@ class EditPlace(EditPrimary):
|
||||
|
||||
self._setup_notebook_tabs(notebook)
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
self.backref_tab.close()
|
||||
|
||||
def save(self, *obj):
|
||||
self.ok_button.set_sensitive(False)
|
||||
if self.object_is_empty():
|
||||
@@ -315,9 +312,9 @@ class EditPlace(EditPrimary):
|
||||
msg = _("Edit Place (%s)") % self.obj.get_title()
|
||||
self.db.transaction_commit(trans, msg)
|
||||
|
||||
self.close()
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
@@ -151,7 +151,13 @@ class EditPrimary(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
return page
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
pass
|
||||
"""Unset all things that can block garbage collection.
|
||||
Finalize rest
|
||||
"""
|
||||
for tab in self.__tabs:
|
||||
if hasattr(tab, '_cleanup_on_exit'):
|
||||
tab._cleanup_on_exit()
|
||||
self.__tabs = None
|
||||
|
||||
def object_is_empty(self):
|
||||
return cmp(self.obj.serialize()[1:],
|
||||
@@ -172,8 +178,14 @@ class EditPrimary(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
def _do_close(self, *obj):
|
||||
self._cleanup_db_connects()
|
||||
self.dbstate.disconnect(self.dbstate_connect_key)
|
||||
self._cleanup_connects()
|
||||
self._cleanup_on_exit()
|
||||
self.get_from_handle = None
|
||||
self.get_from_gramps_id = None
|
||||
ManagedWindow.ManagedWindow.close(self)
|
||||
self.dbstate = None
|
||||
self.uistate = None
|
||||
self.db = None
|
||||
|
||||
def _cleanup_db_connects(self):
|
||||
"""
|
||||
@@ -187,6 +199,23 @@ class EditPrimary(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
for tab in self.__tabs:
|
||||
if hasattr(tab, 'callman'):
|
||||
tab._cleanup_callbacks()
|
||||
|
||||
def _cleanup_connects(self):
|
||||
"""
|
||||
Connects to interface elements to things outside the element should be
|
||||
removed before destroying the interface
|
||||
"""
|
||||
self._cleanup_local_connects()
|
||||
for tab in [tab for tab in self.__tabs if hasattr(tab, '_cleanup_local_connects')]:
|
||||
tab._cleanup_local_connects()
|
||||
|
||||
def _cleanup_local_connects(self):
|
||||
"""
|
||||
Connects to interface elements to things outside the element should be
|
||||
removed before destroying the interface. This methods cleans connects
|
||||
of the main interface, not of the displaytabs.
|
||||
"""
|
||||
pass
|
||||
|
||||
def check_for_close(self, handles):
|
||||
"""
|
||||
@@ -236,7 +265,9 @@ class EditPrimary(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
self.obj.serialize()[1:]) != 0
|
||||
|
||||
def save(self, *obj):
|
||||
pass
|
||||
""" Save changes and close. Inheriting classes must implement this
|
||||
"""
|
||||
self.close()
|
||||
|
||||
def set_contexteventbox(self, eventbox):
|
||||
"""Set the contextbox that grabs button presses if not grabbed
|
||||
|
||||
@@ -186,7 +186,6 @@ class EditReference(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
button.connect('clicked',self.close_and_cancel)
|
||||
|
||||
def close_and_cancel(self, obj):
|
||||
self._cleanup_on_exit()
|
||||
self.close(obj)
|
||||
|
||||
def check_for_close(self, handles):
|
||||
@@ -205,11 +204,28 @@ class EditReference(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
button.set_sensitive(True)
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
pass
|
||||
"""Unset all things that can block garbage collection.
|
||||
Finalize rest
|
||||
"""
|
||||
for tab in self.__tabs:
|
||||
if hasattr(tab, '_cleanup_on_exit'):
|
||||
tab._cleanup_on_exit()
|
||||
self.__tabs = None
|
||||
self.dbstate = None
|
||||
self.uistate = None
|
||||
self.source_ref = None
|
||||
self.source = None
|
||||
self.update = None
|
||||
self.warn_box = None
|
||||
self.db = None
|
||||
self.callman.database = None
|
||||
self.callman = None
|
||||
|
||||
def close(self,*obj):
|
||||
self._cleanup_db_connects()
|
||||
self._cleanup_connects()
|
||||
ManagedWindow.ManagedWindow.close(self)
|
||||
self._cleanup_on_exit()
|
||||
|
||||
def _cleanup_db_connects(self):
|
||||
"""
|
||||
@@ -222,3 +238,20 @@ class EditReference(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
self._cleanup_callbacks()
|
||||
for tab in [tab for tab in self.__tabs if hasattr(tab, 'callman')]:
|
||||
tab._cleanup_callbacks()
|
||||
|
||||
def _cleanup_connects(self):
|
||||
"""
|
||||
Connects to interface elements to things outside the element should be
|
||||
removed before destroying the interface
|
||||
"""
|
||||
self._cleanup_local_connects()
|
||||
for tab in [tab for tab in self.__tabs if hasattr(tab, '_cleanup_local_connects')]:
|
||||
tab._cleanup_local_connects()
|
||||
|
||||
def _cleanup_local_connects(self):
|
||||
"""
|
||||
Connects to interface elements to things outside the element should be
|
||||
removed before destroying the interface. This methods cleans connects
|
||||
of the main interface, not of the displaytabs.
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -190,9 +190,6 @@ class EditRepository(EditPrimary):
|
||||
self.db.transaction_commit(trans, msg)
|
||||
self.close()
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
self.backref_list.close()
|
||||
|
||||
class DeleteRepositoryQuery(object):
|
||||
def __init__(self, dbstate, uistate, repository, sources):
|
||||
self.obj = repository
|
||||
|
||||
@@ -106,7 +106,20 @@ class EditSecondary(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
return page
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
pass
|
||||
"""Unset all things that can block garbage collection.
|
||||
Finalize rest
|
||||
"""
|
||||
for tab in self.__tabs:
|
||||
if hasattr(tab, '_cleanup_on_exit'):
|
||||
tab._cleanup_on_exit()
|
||||
self.__tabs = None
|
||||
self.dbstate = None
|
||||
self.uistate = None
|
||||
self.obj = None
|
||||
self.db = None
|
||||
self.callback = None
|
||||
self.callman.database = None
|
||||
self.callman = None
|
||||
|
||||
def define_ok_button(self,button,function):
|
||||
button.connect('clicked',function)
|
||||
@@ -121,8 +134,9 @@ class EditSecondary(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
|
||||
def close(self,*obj):
|
||||
self._cleanup_db_connects()
|
||||
self._cleanup_on_exit()
|
||||
self._cleanup_connects()
|
||||
ManagedWindow.ManagedWindow.close(self)
|
||||
self._cleanup_on_exit()
|
||||
|
||||
def _cleanup_db_connects(self):
|
||||
"""
|
||||
@@ -135,3 +149,20 @@ class EditSecondary(ManagedWindow.ManagedWindow, DbGUIElement):
|
||||
self._cleanup_callbacks()
|
||||
for tab in [tab for tab in self.__tabs if hasattr(tab, 'callman')]:
|
||||
tab._cleanup_callbacks()
|
||||
|
||||
def _cleanup_connects(self):
|
||||
"""
|
||||
Connects to interface elements to things outside the element should be
|
||||
removed before destroying the interface
|
||||
"""
|
||||
self._cleanup_local_connects()
|
||||
for tab in [tab for tab in self.__tabs if hasattr(tab, '_cleanup_local_connects')]:
|
||||
tab._cleanup_local_connects()
|
||||
|
||||
def _cleanup_local_connects(self):
|
||||
"""
|
||||
Connects to interface elements to things outside the element should be
|
||||
removed before destroying the interface. This methods cleans connects
|
||||
of the main interface, not of the displaytabs.
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -208,9 +208,6 @@ class EditSource(EditPrimary):
|
||||
self.db.transaction_commit(trans, msg)
|
||||
self.close()
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
self.backref_tab.close()
|
||||
|
||||
class DeleteSrcQuery(object):
|
||||
def __init__(self, dbstate, uistate, source, the_lists):
|
||||
self.source = source
|
||||
|
||||
@@ -158,39 +158,39 @@ class EditSourceRef(EditReference):
|
||||
self._add_tab(notebook_src, self.primtab)
|
||||
self._add_tab(notebook_ref, self.reftab)
|
||||
|
||||
self.note_tab = self._add_tab(
|
||||
notebook_src,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_note_list(),
|
||||
notetype=gen.lib.NoteType.SOURCE))
|
||||
|
||||
self.gallery_tab = self._add_tab(
|
||||
notebook_src,
|
||||
GalleryTab(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_media_list()))
|
||||
|
||||
self.data_tab = self._add_tab(
|
||||
notebook_src,
|
||||
DataEmbedList(self.dbstate, self.uistate, self.track,
|
||||
self.source))
|
||||
|
||||
self.repo_tab = self._add_tab(
|
||||
notebook_src,
|
||||
RepoEmbedList(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_reporef_list()))
|
||||
|
||||
self.srcref_list = self._add_tab(
|
||||
notebook_src,
|
||||
SourceBackRefList(self.dbstate,self.uistate, self.track,
|
||||
self.note_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_note_list(),
|
||||
notetype=gen.lib.NoteType.SOURCE)
|
||||
self._add_tab(notebook_src, self.note_tab)
|
||||
self.track_ref_for_deletion("note_tab")
|
||||
|
||||
self.gallery_tab = GalleryTab(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_media_list())
|
||||
self._add_tab(notebook_src, self.gallery_tab)
|
||||
self.track_ref_for_deletion("gallery_tab")
|
||||
|
||||
self.data_tab = DataEmbedList(self.dbstate, self.uistate, self.track,
|
||||
self.source)
|
||||
self._add_tab(notebook_src, self.data_tab)
|
||||
self.track_ref_for_deletion("data_tab")
|
||||
|
||||
self.repo_tab = RepoEmbedList(self.dbstate, self.uistate, self.track,
|
||||
self.source.get_reporef_list())
|
||||
self._add_tab(notebook_src, self.repo_tab)
|
||||
self.track_ref_for_deletion("repo_tab")
|
||||
|
||||
self.srcref_list = SourceBackRefList(self.dbstate,self.uistate, self.track,
|
||||
self.db.find_backlink_handles(self.source.handle),
|
||||
self.enable_warnbox
|
||||
))
|
||||
)
|
||||
self._add_tab(notebook_src, self.srcref_list)
|
||||
self.track_ref_for_deletion("srcref_list")
|
||||
|
||||
self.comment_tab = self._add_tab(
|
||||
notebook_ref,
|
||||
NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.comment_tab = NoteTab(self.dbstate, self.uistate, self.track,
|
||||
self.source_ref.get_note_list(),
|
||||
notetype=gen.lib.NoteType.SOURCEREF))
|
||||
notetype=gen.lib.NoteType.SOURCEREF)
|
||||
self._add_tab(notebook_ref, self.comment_tab)
|
||||
self.track_ref_for_deletion("comment_tab")
|
||||
|
||||
self._setup_notebook_tabs( notebook_src)
|
||||
self._setup_notebook_tabs( notebook_ref)
|
||||
|
||||
@@ -69,9 +69,12 @@ class BaseSelector(ManagedWindow.ManagedWindow):
|
||||
ManagedWindow.ManagedWindow.__init__(self, uistate, track, self)
|
||||
|
||||
self.renderer = gtk.CellRendererText()
|
||||
self.track_ref_for_deletion("renderer")
|
||||
self.renderer.set_property('ellipsize',pango.ELLIPSIZE_END)
|
||||
|
||||
self.db = dbstate.db
|
||||
self.tree = None
|
||||
self.model = None
|
||||
|
||||
self.glade = Glade()
|
||||
|
||||
@@ -103,6 +106,7 @@ class BaseSelector(ManagedWindow.ManagedWindow):
|
||||
self.skip_list=skip
|
||||
self.build_tree()
|
||||
self.selection = self.tree.get_selection()
|
||||
self.track_ref_for_deletion("selection")
|
||||
|
||||
self._local_init()
|
||||
self._set_size()
|
||||
@@ -152,14 +156,15 @@ class BaseSelector(ManagedWindow.ManagedWindow):
|
||||
|
||||
def run(self):
|
||||
val = self.window.run()
|
||||
result = None
|
||||
if val == gtk.RESPONSE_OK:
|
||||
id_list = self.get_selected_ids()
|
||||
self.close()
|
||||
if id_list and id_list[0]:
|
||||
return self.get_from_handle_func()(id_list[0])
|
||||
result = self.get_from_handle_func()(id_list[0])
|
||||
self.close()
|
||||
elif val != gtk.RESPONSE_DELETE_EVENT:
|
||||
self.close()
|
||||
return None
|
||||
return result
|
||||
|
||||
def _on_row_activated(self, treeview, path, view_col):
|
||||
self.window.response(gtk.RESPONSE_OK)
|
||||
@@ -255,6 +260,7 @@ class BaseSelector(ManagedWindow.ManagedWindow):
|
||||
self.add_columns(self.tree)
|
||||
|
||||
#reset the model with correct sorting
|
||||
self.clear_model()
|
||||
self.model = self.get_model_class()(self.db, self.sort_col,
|
||||
self.sortorder,
|
||||
sort_map=self.column_order(),
|
||||
@@ -299,7 +305,7 @@ class BaseSelector(ManagedWindow.ManagedWindow):
|
||||
|
||||
def show_toggle(self, obj):
|
||||
filter_info = None if obj.get_active() else self.filter
|
||||
|
||||
self.clear_model()
|
||||
self.model = self.get_model_class()(self.db, self.sort_col,
|
||||
self.sortorder,
|
||||
sort_map=self.column_order(),
|
||||
@@ -307,3 +313,24 @@ class BaseSelector(ManagedWindow.ManagedWindow):
|
||||
search=filter_info)
|
||||
self.tree.set_model(self.model)
|
||||
self.tree.grab_focus()
|
||||
|
||||
def clear_model(self):
|
||||
if self.model:
|
||||
self.tree.set_model(None)
|
||||
if hasattr(self.model, 'destroy'):
|
||||
self.model.destroy()
|
||||
self.model = None
|
||||
|
||||
def _cleanup_on_exit(self):
|
||||
"""Unset all things that can block garbage collection.
|
||||
Finalize rest
|
||||
"""
|
||||
self.clear_model()
|
||||
self.db = None
|
||||
self.tree = None
|
||||
self.columns = None
|
||||
self.search_bar.destroy()
|
||||
|
||||
def close(self, *obj):
|
||||
ManagedWindow.ManagedWindow.close(self)
|
||||
self._cleanup_on_exit()
|
||||
|
||||
@@ -258,6 +258,9 @@ class ListView(NavigationView):
|
||||
filter_info = (False, value, value[0] in self.exact_search())
|
||||
|
||||
if self.dirty or not self.model:
|
||||
if self.model:
|
||||
self.list.set_model(None)
|
||||
self.model.destroy()
|
||||
self.model = self.make_model(self.dbstate.db, self.sort_col,
|
||||
search=filter_info,
|
||||
sort_map=self.column_order())
|
||||
|
||||
@@ -101,6 +101,17 @@ class EventModel(FlatBaseModel):
|
||||
FlatBaseModel.__init__(self, db, scol, order, tooltip_column=9,
|
||||
search=search, skip=skip, sort_map=sort_map)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.gen_cursor = None
|
||||
self.map = None
|
||||
self.fmap = None
|
||||
self.smap = None
|
||||
FlatBaseModel.destroy(self)
|
||||
|
||||
def on_get_n_columns(self):
|
||||
return len(self.fmap)+1
|
||||
|
||||
|
||||
@@ -90,6 +90,17 @@ class FamilyModel(FlatBaseModel):
|
||||
FlatBaseModel.__init__(self, db, scol, order, tooltip_column=6,
|
||||
search=search, skip=skip, sort_map=sort_map)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.gen_cursor = None
|
||||
self.map = None
|
||||
self.fmap = None
|
||||
self.smap = None
|
||||
FlatBaseModel.destroy(self)
|
||||
|
||||
def marker_column(self):
|
||||
"""
|
||||
Return the column for marker colour.
|
||||
|
||||
@@ -122,6 +122,14 @@ class FlatNodeMap(object):
|
||||
self._reverse = False
|
||||
self.__corr = (0, 1)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
self._index2hndl = None
|
||||
self._fullhndl = None
|
||||
self._hndl2index = None
|
||||
|
||||
def set_path_map(self, index2hndllist, fullhndllist, identical=True,
|
||||
reverse=False):
|
||||
"""
|
||||
@@ -414,6 +422,18 @@ class FlatBaseModel(gtk.GenericTreeModel):
|
||||
_LOG.debug(self.__class__.__name__ + ' __init__ ' +
|
||||
str(time.clock() - cput) + ' sec')
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.sort_func = None
|
||||
if self.node_map:
|
||||
self.node_map.destroy()
|
||||
self.node_map = None
|
||||
self.rebuild_data = None
|
||||
self.search = None
|
||||
|
||||
def set_search(self, search):
|
||||
"""
|
||||
Change the search function that filters the data in the model.
|
||||
|
||||
@@ -83,6 +83,17 @@ class MediaModel(FlatBaseModel):
|
||||
FlatBaseModel.__init__(self, db, scol, order, tooltip_column=7,
|
||||
search=search, skip=skip, sort_map=sort_map)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.gen_cursor = None
|
||||
self.map = None
|
||||
self.fmap = None
|
||||
self.smap = None
|
||||
FlatBaseModel.destroy(self)
|
||||
|
||||
def on_get_n_columns(self):
|
||||
return len(self.fmap)+1
|
||||
|
||||
|
||||
@@ -78,6 +78,17 @@ class NoteModel(FlatBaseModel):
|
||||
FlatBaseModel.__init__(self, db, scol, order, search=search,
|
||||
skip=skip, sort_map=sort_map)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.gen_cursor = None
|
||||
self.map = None
|
||||
self.fmap = None
|
||||
self.smap = None
|
||||
FlatBaseModel.destroy(self)
|
||||
|
||||
def marker_column(self):
|
||||
"""
|
||||
Return the column for marker colour.
|
||||
|
||||
@@ -146,6 +146,17 @@ class PeopleBaseModel(object):
|
||||
self.lru_bdate = LRU(PeopleBaseModel._CACHE_SIZE)
|
||||
self.lru_ddate = LRU(PeopleBaseModel._CACHE_SIZE)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.gen_cursor = None
|
||||
self.map = None
|
||||
self.fmap = None
|
||||
self.smap = None
|
||||
self.clear_local_cache()
|
||||
|
||||
def marker_column(self):
|
||||
"""
|
||||
Return the column for marker colour.
|
||||
@@ -454,7 +465,6 @@ class PersonListModel(PeopleBaseModel, FlatBaseModel):
|
||||
"""
|
||||
def __init__(self, db, scol=0, order=gtk.SORT_ASCENDING, search=None,
|
||||
skip=set(), sort_map=None):
|
||||
|
||||
PeopleBaseModel.__init__(self, db)
|
||||
FlatBaseModel.__init__(self, db, search=search, skip=skip,
|
||||
tooltip_column=12,
|
||||
@@ -464,6 +474,13 @@ class PersonListModel(PeopleBaseModel, FlatBaseModel):
|
||||
""" Clear the LRU cache """
|
||||
PeopleBaseModel.clear_local_cache(self, handle)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
PeopleBaseModel.destroy(self)
|
||||
FlatBaseModel.destroy(self)
|
||||
|
||||
class PersonTreeModel(PeopleBaseModel, TreeBaseModel):
|
||||
"""
|
||||
Hierarchical people model.
|
||||
@@ -475,6 +492,15 @@ class PersonTreeModel(PeopleBaseModel, TreeBaseModel):
|
||||
TreeBaseModel.__init__(self, db, 12, search=search, skip=skip,
|
||||
scol=scol, order=order, sort_map=sort_map)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
PeopleBaseModel.destroy(self)
|
||||
self.hmap = None
|
||||
self.number_items = None
|
||||
TreeBaseModel.destroy(self)
|
||||
|
||||
def _set_base_data(self):
|
||||
"""See TreeBaseModel, we also set some extra lru caches
|
||||
"""
|
||||
|
||||
@@ -117,6 +117,16 @@ class PlaceBaseModel(object):
|
||||
self.column_handle,
|
||||
]
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.gen_cursor = None
|
||||
self.map = None
|
||||
self.fmap = None
|
||||
self.smap = None
|
||||
|
||||
def on_get_n_columns(self):
|
||||
return len(self.fmap)+1
|
||||
|
||||
@@ -218,6 +228,13 @@ class PlaceListModel(PlaceBaseModel, FlatBaseModel):
|
||||
FlatBaseModel.__init__(self, db, scol, order, tooltip_column=14,
|
||||
search=search, skip=skip, sort_map=sort_map)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
PlaceBaseModel.destroy(self)
|
||||
FlatBaseModel.destroy(self)
|
||||
|
||||
def column_name(self, data):
|
||||
return unicode(data[2])
|
||||
|
||||
@@ -240,6 +257,15 @@ class PlaceTreeModel(PlaceBaseModel, TreeBaseModel):
|
||||
nrgroups = 3,
|
||||
group_can_have_handle = True)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
PlaceBaseModel.destroy(self)
|
||||
self.hmap = None
|
||||
self.number_items = None
|
||||
TreeBaseModel.destroy(self)
|
||||
|
||||
def _set_base_data(self):
|
||||
"""See TreeBaseModel, for place, most have been set in init of
|
||||
PlaceBaseModel
|
||||
|
||||
@@ -94,6 +94,18 @@ class RepositoryModel(FlatBaseModel):
|
||||
FlatBaseModel.__init__(self, db, scol, order, tooltip_column=14,
|
||||
search=search, skip=skip, sort_map=sort_map)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.gen_cursor = None
|
||||
self.get_handles = None
|
||||
self.map = None
|
||||
self.fmap = None
|
||||
self.smap = None
|
||||
FlatBaseModel.destroy(self)
|
||||
|
||||
def on_get_n_columns(self):
|
||||
return len(self.fmap)+1
|
||||
|
||||
|
||||
@@ -77,6 +77,17 @@ class SourceModel(FlatBaseModel):
|
||||
FlatBaseModel.__init__(self,db,scol, order,tooltip_column=7,search=search,
|
||||
skip=skip, sort_map=sort_map)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.gen_cursor = None
|
||||
self.map = None
|
||||
self.fmap = None
|
||||
self.smap = None
|
||||
FlatBaseModel.destroy(self)
|
||||
|
||||
def on_get_n_columns(self):
|
||||
return len(self.fmap)+1
|
||||
|
||||
|
||||
@@ -173,6 +173,17 @@ class NodeMap(object):
|
||||
"""
|
||||
def __init__(self):
|
||||
self.id2node = {}
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
## for key, item in self.id2node.iteritems():
|
||||
## item.prev = None
|
||||
## item.next = None
|
||||
## item.parent = None
|
||||
## item.children = []
|
||||
self.id2node.clear()
|
||||
|
||||
def add_node(self, node):
|
||||
"""
|
||||
@@ -321,6 +332,22 @@ class TreeBaseModel(gtk.GenericTreeModel):
|
||||
_LOG.debug(self.__class__.__name__ + ' __init__ ' +
|
||||
str(time.clock() - cput) + ' sec')
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.sort_func = None
|
||||
if self.nodemap:
|
||||
self.nodemap.destroy()
|
||||
self.nodemap = None
|
||||
self.rebuild_data = None
|
||||
self._build_data = None
|
||||
self.search = None
|
||||
self.current_filter = None
|
||||
self.clear_cache()
|
||||
self.lru_data = None
|
||||
|
||||
def _set_base_data(self):
|
||||
"""
|
||||
This method must be overwritten in the inheriting class, setting
|
||||
|
||||
@@ -485,7 +485,7 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
else:
|
||||
self.text += i
|
||||
|
||||
def process_spaces (self, line, format):
|
||||
def process_spaces(line, format):
|
||||
"""
|
||||
Function to process spaces in text lines for flowed and pre-formatted notes.
|
||||
line : text to process
|
||||
|
||||
@@ -618,6 +618,11 @@ class GedcomWriter(UpdateCallback):
|
||||
continue
|
||||
|
||||
val = libgedcom.personalConstantEvents.get(etype, "").strip()
|
||||
|
||||
role = int(event_ref.get_role())
|
||||
|
||||
if role != gen.lib.EventRoleType.PRIMARY:
|
||||
continue
|
||||
|
||||
if val and val.strip():
|
||||
if val in NEEDS_PARAMETER:
|
||||
|
||||
@@ -431,9 +431,11 @@ class GeneWebParser(object):
|
||||
field = fields[idx]
|
||||
idx += 1
|
||||
if field.startswith("+"):
|
||||
field = field[1:]
|
||||
mar_date = self.parse_date(self.decode(field))
|
||||
LOG.debug(" Married at: %s" % field)
|
||||
elif field.startswith("-"):
|
||||
field = field[1:]
|
||||
div_date = self.parse_date(self.decode(field))
|
||||
LOG.debug(" Div at: %s" % field)
|
||||
elif field == "#mp" and idx < len(fields):
|
||||
@@ -465,13 +467,17 @@ class GeneWebParser(object):
|
||||
gen.lib.EventType.MARRIAGE, None, mar_date, mar_place, mar_source)
|
||||
mar_ref = gen.lib.EventRef()
|
||||
mar_ref.set_reference_handle(mar.get_handle())
|
||||
mar_ref.set_role(gen.lib.EventRoleType.FAMILY)
|
||||
self.current_family.add_event_ref(mar_ref)
|
||||
self.current_family.set_relationship(
|
||||
gen.lib.FamilyRelType(gen.lib.FamilyRelType.MARRIED))
|
||||
|
||||
if div_date:
|
||||
div = self.create_event(
|
||||
gen.lib.EventType.DIVORCE, None, div_date, None, None)
|
||||
div_ref = gen.lib.EventRef()
|
||||
div_ref.set_reference_handle(div.get_handle())
|
||||
div_ref.set_role(gen.lib.EventRoleType.FAMILY)
|
||||
self.current_family.add_event_ref(div_ref)
|
||||
|
||||
if sep_date or engaged:
|
||||
@@ -479,6 +485,7 @@ class GeneWebParser(object):
|
||||
gen.lib.EventType.ENGAGEMENT, None, sep_date, None, None)
|
||||
sep_ref = gen.lib.EventRef()
|
||||
sep_ref.set_reference_handle(sep.get_handle())
|
||||
sep_ref.set_role(gen.lib.EventRoleType.FAMILY)
|
||||
self.current_family.add_event_ref(sep_ref)
|
||||
|
||||
if not married:
|
||||
|
||||
@@ -118,6 +118,7 @@ import LdsUtils
|
||||
import Utils
|
||||
from DateHandler._DateParser import DateParser
|
||||
from gen.db.dbconst import EVENT_KEY
|
||||
from QuestionDialog import WarningDialog
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -5433,7 +5434,12 @@ class GedcomParser(UpdateCallback):
|
||||
"""
|
||||
if state.genby == "GRAMPS":
|
||||
self.gedsource = self.gedmap.get_from_source_tag(line.data)
|
||||
|
||||
|
||||
if state.genby.upper() == "LEGACY":
|
||||
fname = os.path.basename(self.filename)
|
||||
WarningDialog(_("Import of GEDCOM file %s with DEST=%s, could cause errors in the resulting database!") % \
|
||||
(fname, state.genby), _("Look for nameless events."))
|
||||
|
||||
def __header_plac(self, line, state):
|
||||
"""
|
||||
@param line: The current line in GedLine format
|
||||
|
||||
@@ -427,7 +427,8 @@ class Html(list):
|
||||
)
|
||||
self[0:0] = [xmldecl]
|
||||
#
|
||||
def addDOCTYPE(self, name='html', external_id=_XHTML10_STRICT, *args):
|
||||
def addDOCTYPE(self, name='html', public='PUBLIC',
|
||||
external_id=_XHTML10_STRICT, *args):
|
||||
"""
|
||||
Add a DOCTYPE statement to the start of the list
|
||||
|
||||
@@ -440,8 +441,9 @@ class Html(list):
|
||||
:param args: 0 or more positional parameters to be added to this
|
||||
DOCTYPE.
|
||||
"""
|
||||
doctype = '<!DOCTYPE %s %s%s>' % (
|
||||
name,
|
||||
doctype = '<!DOCTYPE %s %s %s%s>' % (
|
||||
name,
|
||||
public,
|
||||
external_id,
|
||||
' %s'*len(args) % args
|
||||
)
|
||||
|
||||
@@ -119,7 +119,7 @@ def process_spaces(intext, format):
|
||||
outtext += char
|
||||
elif state == SPACEHOLD:
|
||||
if char == " ":
|
||||
outtext += " "
|
||||
outtext += " "
|
||||
state = NORMAL
|
||||
elif char == "<":
|
||||
outtext += " "+char
|
||||
|
||||
@@ -21,7 +21,8 @@ pkgdata_PYTHON = \
|
||||
rel_pl.py\
|
||||
rel_pt.py\
|
||||
rel_ru.py\
|
||||
rel_sk.py\
|
||||
rel_sk.py\
|
||||
rel_sl.py\
|
||||
rel_sv.py
|
||||
|
||||
pkgpyexecdir = @pkgpyexecdir@/plugins/rel
|
||||
|
||||
@@ -0,0 +1,337 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2003-2005 Donald N. Allingham
|
||||
# Copyright (C) 2008 Brian G. Matherly
|
||||
# Copyright (C) 2009-2010 Andrew I Baznikin
|
||||
#
|
||||
# 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:rel_sl.py 9912 2008-01-22 09:17:46Z acraphae $
|
||||
|
||||
# Written by Bernard Banko, inspired from rel_ru.py by Alex Roitman.
|
||||
"""
|
||||
Slovenian-specific definitions of relationships
|
||||
"""
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
import gen.lib
|
||||
import Relationship
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
_ancestors = [ u"", u"starš", u"stari starš", u"prastari starš" ]
|
||||
_fathers = [ u"", u"oče", u"ded", u"praded", u"prapraded" ]
|
||||
_mothers = [ u"", u"mati", u"babica", u"prababica", u"praprababica" ]
|
||||
_descendants = [
|
||||
u"", u"otrok", u"vnuk(inja)", u"pravnuk(inja)", u"prapravnuk(inja)" ]
|
||||
_sons = [ u"", u"sin", u"vnuk", u"pravnuk", u"prapravnuk" ]
|
||||
_daughters = [ u"", u"hči", u"vnukinja", u"pravnukinja", u"prapravnukinja" ]
|
||||
_maleCousins = [ u"", u"brat", u"bratranec", u"mali bratranec" ]
|
||||
_femaleCousins = [ u"", u"sestra", u"sestrična", u"mala sestrična" ]
|
||||
_someCousins = [ u"", u"brat ali sestra", u"bratranec ali sestrična",
|
||||
u"mali bratranec ali mala sestrična" ]
|
||||
_aunts = [ u"", u"teta", u"stara teta", u"prateta", u"praprateta" ]
|
||||
_uncles = [ u"", u"stric", u"stari stric", u"prastric", u"praprastric" ]
|
||||
_nieces = [ u"", u"nečakinja", u"pranečakinja", u"prapranečakinja" ]
|
||||
_nephews = [ u"", u"nečak", u"pranečak", u"prapranečak" ]
|
||||
|
||||
#plural
|
||||
_children = [ u"", u"otroci", u"vnuki", u"pravnuki", u"prapravnuki" ]
|
||||
_parents = [ u"", u"starši", u"stari starši", u"prastarši", u"praprastarši" ]
|
||||
_siblings = [ u"", u"sorojenci", u"strici", u"stari strici", u"prastrici",
|
||||
u"praprastrici" ]
|
||||
_neph_niec = [ u"", u"nečaki", u"pranečaki", u"prapranečaki" ]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class RelationshipCalculator(Relationship.RelationshipCalculator):
|
||||
"""
|
||||
RelationshipCalculator Class
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
Relationship.RelationshipCalculator.__init__(self)
|
||||
|
||||
def getAncestor(self, level):
|
||||
if level > len(_ancestors)-1:
|
||||
return u"%s-krat-pra-prednik" % (level-2)
|
||||
else:
|
||||
return _ancestors[level]
|
||||
|
||||
def getFather(self, level):
|
||||
if level > len(_fathers)-1:
|
||||
return u"%s-krat-pra-ded" % (level-2)
|
||||
else:
|
||||
return _fathers[level]
|
||||
|
||||
def getMother(self, level):
|
||||
if level > len(_mothers)-1:
|
||||
return u"%s-krat-pra-babica" % (level-2)
|
||||
else:
|
||||
return _mothers[level]
|
||||
|
||||
def getSon(self, level):
|
||||
if level > len(_sons)-1:
|
||||
return u"%s-krat-pra-vnuk" % (level-2)
|
||||
else:
|
||||
return _sons[level]
|
||||
|
||||
def getDaughter(self, level):
|
||||
if level > len(_daughters)-1:
|
||||
return u"%s-krat-pra-vnukinja" % (level-2)
|
||||
else:
|
||||
return _daughters[level]
|
||||
|
||||
def getDescendant(self, level):
|
||||
if level > len(_descendants)-1:
|
||||
return u"%s-krat-pra-vnuk(inja)" % (level-2)
|
||||
else:
|
||||
return _descendants[level]
|
||||
|
||||
def getMaleCousin(self, level):
|
||||
if level > len(_maleCousins)-1:
|
||||
return u"bratranec v %s. kolenu" % (level*2)
|
||||
else:
|
||||
return _maleCousins[level]
|
||||
|
||||
def getFemaleCousin(self, level):
|
||||
if level > len(_femaleCousins)-1:
|
||||
return u"sestrična v %s. kolenu" % (level*2)
|
||||
else:
|
||||
return _femaleCousins[level]
|
||||
|
||||
def getSomeCousin(self, level):
|
||||
if level > len(_someCousins)-1:
|
||||
return u"bratranec ali sestrična v %s. kolenu" % (level*2)
|
||||
else:
|
||||
return _someCousins[level]
|
||||
|
||||
def getSuffix(self, distance, level):
|
||||
# distance-level = 2Gb <=> Gb=1
|
||||
if distance-level == 2 or distance < 6:
|
||||
return u""
|
||||
else:
|
||||
return u" v %s. kolenu" % (distance)
|
||||
|
||||
def getAunt(self, distance, level):
|
||||
if distance == 5 and level == 1:
|
||||
return u"mala teta"
|
||||
elif level > len(_aunts)-1:
|
||||
return u"%s-krat-pra-teta%s" % (level-2, self.getSuffix(distance, level))
|
||||
else:
|
||||
return u"%s%s" % (_aunts[level], self.getSuffix(distance, level))
|
||||
|
||||
def getUncle(self, distance, level):
|
||||
if distance == 5 and level == 1:
|
||||
return u"mali stric"
|
||||
elif level > len(_uncles)-1:
|
||||
return u"%s-krat-pra-stric%s" % (level-2, self.getSuffix(distance, level))
|
||||
else:
|
||||
return u"%s%s" % (_uncles[level], self.getSuffix(distance, level))
|
||||
|
||||
def getNiece(self, distance, level):
|
||||
if distance == 5 and level == 1:
|
||||
return u"mala nečakinja"
|
||||
elif level > len(_nieces)-1:
|
||||
return u"%s-krat-pra-nečakinja%s" % (level-1, self.getSuffix(distance, level))
|
||||
else:
|
||||
return u"%s%s" % (_nieces[level], self.getSuffix(distance, level))
|
||||
|
||||
def getNephew(self, distance, level):
|
||||
if distance == 5 and level == 1:
|
||||
return u"mali nečak"
|
||||
elif level > len(_nephews)-1:
|
||||
return u"%s-krat-pra-nečak%s" % (level-1, self.getSuffix(distance, level))
|
||||
else:
|
||||
return u"%s%s" % (_nephews[level], self.getSuffix(distance, level))
|
||||
|
||||
def get_single_relationship_string(
|
||||
self, Ga, Gb, gender_a, gender_b, reltocommon_a, reltocommon_b,
|
||||
only_birth=True, in_law_a=False, in_law_b=False):
|
||||
"""
|
||||
Provide a string that describes the relationsip between a person, and
|
||||
another person. E.g. "grandparent" or "child".
|
||||
To be used as: 'person b is the grandparent of a', this will
|
||||
be in translation string :
|
||||
'person b is the %(relation)s of a'
|
||||
Note that languages with gender should add 'the' inside the
|
||||
translation, so eg in french:
|
||||
'person b est %(relation)s de a'
|
||||
where relation will be here: le grandparent
|
||||
|
||||
Ga and Gb can be used to mathematically calculate the relationship.
|
||||
See the Wikipedia entry for more information:
|
||||
http://en.wikipedia.org/wiki/Cousin#Mathematical_definitions
|
||||
"""
|
||||
if Gb == 0:
|
||||
if Ga == 0: rel_str = "ista oseba"
|
||||
elif gender_b == gen.lib.Person.MALE:
|
||||
rel_str = (self.getFather(Ga))
|
||||
elif gender_b == gen.lib.Person.FEMALE:
|
||||
rel_str = (self.getMother(Ga))
|
||||
else:
|
||||
rel_str = (self.getAncestor(Ga))
|
||||
elif Ga == 0:
|
||||
if gender_b == gen.lib.Person.MALE:
|
||||
rel_str = (self.getSon(Gb))
|
||||
elif gender_b == gen.lib.Person.FEMALE:
|
||||
rel_str = (self.getDaughter(Gb))
|
||||
else:
|
||||
rel_str = (self.getDescendant(Gb))
|
||||
elif Ga == Gb:
|
||||
if gender_b == gen.lib.Person.MALE:
|
||||
rel_str = (self.getMaleCousin(Gb))
|
||||
elif gender_b == gen.lib.Person.FEMALE:
|
||||
rel_str = (self.getFemaleCousin(Gb))
|
||||
else:
|
||||
rel_str = (self.getSomeCousin(Gb))
|
||||
elif Ga > Gb:
|
||||
if gender_b == gen.lib.Person.FEMALE:
|
||||
rel_str = (self.getAunt(Ga+Gb, Ga-Gb))
|
||||
else:
|
||||
rel_str = (self.getUncle(Ga+Gb, Ga-Gb)) # we'll use male for unknown sex
|
||||
else: #Ga < Gb
|
||||
if gender_b == gen.lib.Person.FEMALE:
|
||||
rel_str = (self.getNiece(Ga+Gb, Gb-Ga))
|
||||
else:
|
||||
rel_str = (self.getNephew(Ga+Gb, Gb-Ga)) # we'll use male for unknown sex
|
||||
return rel_str
|
||||
|
||||
|
||||
def get_sibling_relationship_string(self, sib_type, gender_a, gender_b,
|
||||
in_law_a=False, in_law_b=False):
|
||||
""" Determine the string giving the relation between two siblings of
|
||||
type sib_type.
|
||||
Eg: b is the brother of a
|
||||
Here 'brother' is the string we need to determine
|
||||
This method gives more details about siblings than
|
||||
get_single_relationship_string can do.
|
||||
DON'T TRANSLATE THIS PROCEDURE IF LOGIC IS EQUAL IN YOUR LANGUAGE,
|
||||
AND SAME METHODS EXIST (get_uncle, get_aunt, get_sibling
|
||||
"""
|
||||
gender = gender_b #we don't need gender_a
|
||||
inlaw = in_law_a or in_law_b
|
||||
if sib_type == self.HALF_SIB_MOTHER or sib_type == self.HALF_SIB_FATHER:
|
||||
prefix = u"pol"
|
||||
else:
|
||||
prefix = u""
|
||||
|
||||
if sib_type < self.STEP_SIB:
|
||||
# ie. NORM_SIB or one of HALF_SIBs
|
||||
if not inlaw:
|
||||
if gender == gen.lib.Person.MALE:
|
||||
rel_str = u"%sbrat" % (prefix)
|
||||
elif gender == gen.lib.Person.FEMALE:
|
||||
rel_str = u"%ssestra" % (prefix)
|
||||
else:
|
||||
rel_str = u"%sbrat ali %ssestra" % (prefix, prefix)
|
||||
else:
|
||||
if gender == gen.lib.Person.MALE:
|
||||
rel_str = u"%ssvak" % (prefix)
|
||||
elif gender == gen.lib.Person.FEMALE:
|
||||
rel_str = u"%ssvakinja" % (prefix)
|
||||
else:
|
||||
rel_str = u"%ssvak ali %ssvakinja" % (prefix, prefix)
|
||||
else:
|
||||
rel_str = u""
|
||||
return rel_str
|
||||
|
||||
|
||||
def get_plural_relationship_string(
|
||||
self, Ga, Gb, reltocommon_a='', reltocommon_b='', only_birth=True,
|
||||
in_law_a=False, in_law_b=False):
|
||||
|
||||
distance = Ga+Gb
|
||||
rel_str = u"sorodniki v %s. kolenu" % (distance)
|
||||
if Ga == 0:
|
||||
# These are descendants
|
||||
if Gb < len(_children):
|
||||
rel_str = _children[Gb]
|
||||
else:
|
||||
rel_str = u"%s-krat-pra-vnuki" % (Gb-2)
|
||||
elif Gb == 0:
|
||||
# These are parents/grand parents
|
||||
if Ga < len(_parents):
|
||||
rel_str = _parents[Ga]
|
||||
else:
|
||||
rel_str = u"%s-krat-pra-starši" % (Ga-2)
|
||||
elif Gb == 1:
|
||||
# These are siblings/aunts/uncles
|
||||
if Ga < len(_siblings):
|
||||
rel_str = _siblings[Ga]
|
||||
else:
|
||||
rel_str = u"%s-krat-pra-strici" % (Ga-2)
|
||||
elif Ga == 1:
|
||||
# These are nieces/nephews
|
||||
if Gb < len(_neph_niec):
|
||||
rel_str = _neph_niec[Gb]
|
||||
else:
|
||||
rel_str = u"%s-krat-pra-nečaki" % (Gb-1)
|
||||
elif Ga == Gb:
|
||||
# These are cousins in the same generation
|
||||
if Ga == 2:
|
||||
rel_str = u"bratranci"
|
||||
elif Ga == 3:
|
||||
rel_str = u"mali bratranci"
|
||||
else:
|
||||
rel_str = u"bratranci v %s. kolenu" % (distance)
|
||||
elif Ga > Gb:
|
||||
# These are cousins in different generations with the second person
|
||||
# being in a higher generation from the common ancestor than the
|
||||
# first person.
|
||||
level = Ga - Gb
|
||||
if distance == 5:
|
||||
rel_str = u"mali strici"
|
||||
elif level < len(_siblings)-1:
|
||||
# len-1 and level+1 to skip the siblings in uncles' levels
|
||||
rel_str = u"%s v %s. kolenu" % (_siblings[level+1], distance)
|
||||
else:
|
||||
rel_str = u"%s-krat-pra-strici v %s. kolenu" % (level-2, distance)
|
||||
else: #Gb > Ga:
|
||||
# These are cousins in different generations with the second person
|
||||
# being in a lower generation from the common ancestor than the
|
||||
# first person.
|
||||
level = Gb - Ga
|
||||
if distance == 5:
|
||||
rel_str = u"mali nečaki"
|
||||
elif level < len(_neph_niec):
|
||||
rel_str = u"%s v %s. kolenu" % (_neph_niec[level], distance)
|
||||
else:
|
||||
rel_str = u"%s-krat-pra-nečaki v %s. kolenu" % (level-1, distance)
|
||||
if in_law_b == True:
|
||||
rel_str = "zakonci, ki jih imajo %s" % rel_str
|
||||
return rel_str
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""TRANSLATORS, copy this if statement at the bottom of your
|
||||
rel_xx.py module, and test your work with:
|
||||
python src/plugins/rel/rel_xx.py
|
||||
"""
|
||||
from Relationship import test
|
||||
RC = RelationshipCalculator()
|
||||
test(RC, True)
|
||||
#
|
||||
#from PluginMgr import register_relcalc
|
||||
# register_relcalc(RelationshipCalculatorClass,["sl","sl_SI","sl-SI","slovenian","Slovenian","slovenščina"])
|
||||
@@ -253,6 +253,20 @@ plg.relcalcclass = 'RelationshipCalculator'
|
||||
plg.lang_list = ["sk", "SK", "sk_SK", "slovensky", "slovak", "Slovak",
|
||||
"sk_SK.UTF8", "sk_SK.UTF-8", "sk_SK.utf-8", "sk_SK.utf8"]
|
||||
|
||||
# sl
|
||||
plg = newplugin()
|
||||
plg.id = 'relcalc_sl'
|
||||
plg.name = _("Slovenian Relationship Calculator")
|
||||
plg.description = _("Calculates relationships between people")
|
||||
plg.version = '1.0'
|
||||
plg.gramps_target_version = '3.2'
|
||||
plg.status = STABLE
|
||||
plg.fname = 'rel_sl.py'
|
||||
plg.ptype = RELCALC
|
||||
plg.relcalcclass = 'RelationshipCalculator'
|
||||
plg.lang_list = ["sl", "SL", "sl_SI", "slovenščina", "slovenian", "Slovenian",
|
||||
"sl_SI.UTF8", "sl_SI.UTF-8", "sl_SI.utf-8", "sl_SI.utf8"]
|
||||
|
||||
# sv
|
||||
plg = newplugin()
|
||||
plg.id = 'relcalc_sv'
|
||||
|
||||
@@ -102,7 +102,7 @@ class AncestorReport(Report):
|
||||
language = menu.get_option_by_name('trans').get_value()
|
||||
translator = Translator(language)
|
||||
self._ = translator.gettext
|
||||
self.__narrator = Narrator(self.database,
|
||||
self.__narrator = Narrator(self.database, use_fulldate=True,
|
||||
translator=translator)
|
||||
|
||||
def apply_filter(self, person_handle, index, generation=1):
|
||||
|
||||
@@ -97,6 +97,7 @@ GROUP_DICT = {FACTS: [EventType.ADOPT,
|
||||
EventType.PROBATE,
|
||||
EventType.RELIGION,
|
||||
EventType.RETIREMENT,
|
||||
EventType.UNKNOWN,
|
||||
EventType.WILL],
|
||||
FAMILY: [EventType.ANNULMENT,
|
||||
EventType.BLESS,
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#-------------------------------------------------------------------------
|
||||
from __future__ import with_statement
|
||||
import os
|
||||
import sys
|
||||
import cStringIO
|
||||
|
||||
from gen.ggettext import gettext as _
|
||||
@@ -552,8 +553,10 @@ class CheckIntegrity(object):
|
||||
photo_name = Utils.media_path_full(self.db, obj.get_path())
|
||||
if photo_name is not None and photo_name != "" and not Utils.find_file(photo_name):
|
||||
if cl:
|
||||
# Convert to file system encoding before prining
|
||||
fn = os.path.basename(photo_name).encode(sys.getfilesystemencoding())
|
||||
print "Warning: media file %s was not found." \
|
||||
% os.path.basename(photo_name)
|
||||
% fn
|
||||
self.bad_photo.append(ObjectId)
|
||||
else:
|
||||
if missmedia_action == 0:
|
||||
@@ -1627,7 +1630,8 @@ class Report(ManagedWindow.ManagedWindow):
|
||||
|
||||
def __init__(self, uistate, text, cl=0):
|
||||
if cl:
|
||||
print text
|
||||
# Convert to file system encoding before prining
|
||||
print text.encode(sys.getfilesystemencoding())
|
||||
return
|
||||
|
||||
ManagedWindow.ManagedWindow.__init__(self, uistate, [], self)
|
||||
|
||||
@@ -716,15 +716,20 @@ class BasePage(object):
|
||||
# return table to its callers
|
||||
return table
|
||||
|
||||
def source_link(self, handle, name, gid = None, up = False):
|
||||
def source_link(self, handle, name, cindex, gid = None, up = False):
|
||||
"""
|
||||
creates a link to the source
|
||||
"""
|
||||
|
||||
url = self.report.build_url_fname_html(handle, "src", up)
|
||||
name = html_escape( name )
|
||||
|
||||
# begin hyperlink
|
||||
hyper = Html("a", html_escape(name), href = url, title = html_escape(name))
|
||||
hyper = Html( "a", name, href = url, title = name )
|
||||
|
||||
# if cindex has a value, then add the name attribute to the hyperlink
|
||||
if cindex is not None:
|
||||
hyper.attr += ' name = "sref%d"' % cindex
|
||||
|
||||
# add GRAMPS ID
|
||||
if not self.noid and gid:
|
||||
@@ -1506,7 +1511,7 @@ class BasePage(object):
|
||||
mime_type = photo.get_mime_type()
|
||||
|
||||
# get media description
|
||||
descr = photo.get_description()
|
||||
descr = html_escape( photo.get_description() )
|
||||
|
||||
if mime_type:
|
||||
try:
|
||||
@@ -1538,8 +1543,7 @@ class BasePage(object):
|
||||
newpath = newpath.replace('\\',"/")
|
||||
|
||||
# begin hyperlink
|
||||
section += self.media_link(photo_handle, newpath, descr,
|
||||
True, True)
|
||||
section += self.media_link(photo_handle, newpath, descr, True, True)
|
||||
|
||||
except (IOError, OSError), msg:
|
||||
WarningDialog(_("Could not add photo to page"), str(msg))
|
||||
@@ -1712,13 +1716,8 @@ class BasePage(object):
|
||||
# Add this source and its references to the page
|
||||
source = db.get_source_from_handle(shandle)
|
||||
title = source.get_title()
|
||||
list = Html("li") + (
|
||||
Html("a",
|
||||
self.source_link(source.handle, title, source.gramps_id,
|
||||
up=True),
|
||||
name="sref%d" % cindex,
|
||||
inline=True)
|
||||
)
|
||||
list = Html("li") + \
|
||||
self.source_link( shandle, title, cindex, source.gramps_id, up = True)
|
||||
|
||||
ordered1 = Html("ol")
|
||||
citation_ref_list = citation.get_ref_list()
|
||||
@@ -3299,6 +3298,7 @@ class SourceListPage(BasePage):
|
||||
def __init__(self, report, title, handle_set):
|
||||
BasePage.__init__(self, report, title)
|
||||
db = report.database
|
||||
cindex = None
|
||||
|
||||
handle_list = list(handle_set)
|
||||
source_dict = {}
|
||||
@@ -3335,12 +3335,13 @@ class SourceListPage(BasePage):
|
||||
thead += trow
|
||||
|
||||
header_row = [
|
||||
(None, "RowLabel"),
|
||||
(" ", "RowLabel"),
|
||||
(_("Source Name|Name"), "Name") ]
|
||||
|
||||
trow.extend(
|
||||
Html("th", label or " ", class_ = "Column" + colclass, inline = True)
|
||||
for (label, colclass) in header_row)
|
||||
Html("th", label, class_ = "Column" + colclass, inline = True)
|
||||
for (label, colclass) in header_row
|
||||
)
|
||||
|
||||
# begin table body
|
||||
tbody = Html("tbody")
|
||||
@@ -3349,14 +3350,15 @@ class SourceListPage(BasePage):
|
||||
for index, key in enumerate(keys):
|
||||
(source, handle) = source_dict[key]
|
||||
|
||||
trow = ( Html("tr") +
|
||||
trow = Html("tr")
|
||||
|
||||
trow.extend(
|
||||
Html("td", index + 1, class_ = "ColumnRowLabel", inline = True)
|
||||
)
|
||||
)
|
||||
tbody += trow
|
||||
trow += Html("td",
|
||||
self.source_link(handle, source.get_title(),
|
||||
source.gramps_id),
|
||||
class_ = "ColumnName")
|
||||
|
||||
trow += Html("td", self.source_link( handle, source.get_title(),
|
||||
cindex, source.gramps_id), class_ = "ColumnName")
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
|
||||
Reference in New Issue
Block a user