From 5e89b0a417828403a9392c92a846e141069ff64b Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Wed, 25 May 2016 11:08:32 -0400 Subject: [PATCH 01/11] NarrativeWebReport: media_ref handles need not be binary --- gramps/plugins/webreport/narrativeweb.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gramps/plugins/webreport/narrativeweb.py b/gramps/plugins/webreport/narrativeweb.py index a26ad9eac..040302938 100644 --- a/gramps/plugins/webreport/narrativeweb.py +++ b/gramps/plugins/webreport/narrativeweb.py @@ -5108,7 +5108,10 @@ class MediaPages(BasePage): # add unused media media_list = self.dbase_.get_media_handles() for media_ref in media_list: - media_handle = media_ref.decode("utf-8") + if isinstance(media_ref, bytes): + media_handle = media_ref.decode("utf-8") + else: + media_handle = media_ref if media_handle not in self.report.obj_dict[Media]: unused_media_handles.append(media_handle) unused_media_handles = sorted(unused_media_handles, @@ -5542,7 +5545,10 @@ class ThumbnailPreviewPage(BasePage): media_list = self.dbase_.get_media_handles() unused_media_handles = [] for media_ref in media_list: - media_handle = media_ref.decode("utf-8") + if isinstance(media_ref, bytes): + media_handle = media_ref.decode("utf-8") + else: + media_handle = media_ref if media_handle not in self.report.obj_dict[Media]: self.photo_keys.append(media_handle) From 7ea785033156cc5b523c74d1010bd3d66c364d7d Mon Sep 17 00:00:00 2001 From: Nick Hall Date: Wed, 25 May 2016 17:13:51 +0100 Subject: [PATCH 02/11] Tidy up whitespace --- gramps/gen/utils/callback.py | 9 +- gramps/gen/utils/callman.py | 122 ++++++----- gramps/gen/utils/place.py | 381 ++++++++++++++++++----------------- gramps/gen/utils/string.py | 14 +- 4 files changed, 265 insertions(+), 261 deletions(-) diff --git a/gramps/gen/utils/callback.py b/gramps/gen/utils/callback.py index f6bb15bde..90dac722f 100644 --- a/gramps/gen/utils/callback.py +++ b/gramps/gen/utils/callback.py @@ -249,7 +249,8 @@ class Callback: for (k, v) in s.items(): if k in self.__signal_map: # signal name clash - sys.stderr.write("Warning: signal name clash: %s\n" % str(k)) + sys.stderr.write("Warning: signal name clash: %s\n" + % str(k)) self.__signal_map[k] = v # Set to None to prevent a memory leak in this recursive function trav = None @@ -258,8 +259,8 @@ class Callback: # of signals that this instance can emit. self._log("registered signals: \n %s\n" % - "\n ".join([ "%s: %s" % (k, v) for (k, v) - in list(self.__signal_map.items()) ])) + "\n ".join(["%s: %s" % (k, v) for (k, v) + in list(self.__signal_map.items())])) def connect(self, signal_name, callback): @@ -273,7 +274,7 @@ class Callback: # Check that signal exists. if signal_name not in self.__signal_map: self._log("Warning: attempt to connect to unknown signal: %s\n" - % str(signal_name)) + % str(signal_name)) return # Add callable to callback_map diff --git a/gramps/gen/utils/callman.py b/gramps/gen/utils/callman.py index e60c1a268..a4e961423 100644 --- a/gramps/gen/utils/callman.py +++ b/gramps/gen/utils/callman.py @@ -72,17 +72,17 @@ NOTECLASS = 'Note' TAGCLASS = 'Tag' CLASS2KEY = { - PERSONCLASS: PERSONKEY, - FAMILYCLASS: FAMILYKEY, - EVENTCLASS: EVENTKEY, - PLACECLASS: PLACEKEY, - MEDIACLASS: MEDIAKEY, - SOURCECLASS: SOURCEKEY, - CITATIONCLASS: CITATIONKEY, - REPOCLASS: REPOKEY, - NOTECLASS: NOTEKEY, - TAGCLASS: TAGKEY - } + PERSONCLASS: PERSONKEY, + FAMILYCLASS: FAMILYKEY, + EVENTCLASS: EVENTKEY, + PLACECLASS: PLACEKEY, + MEDIACLASS: MEDIAKEY, + SOURCECLASS: SOURCEKEY, + CITATIONCLASS: CITATIONKEY, + REPOCLASS: REPOKEY, + NOTECLASS: NOTEKEY, + TAGCLASS: TAGKEY + } def _return(*args): """ @@ -115,17 +115,17 @@ class CallbackManager: #no handles to track self.database = database self.__handles = { - PERSONKEY: [], - FAMILYKEY: [], - EVENTKEY: [], - PLACEKEY: [], - MEDIAKEY: [], - SOURCEKEY: [], - CITATIONKEY: [], - REPOKEY: [], - NOTEKEY: [], - TAGKEY: [], - } + PERSONKEY: [], + FAMILYKEY: [], + EVENTKEY: [], + PLACEKEY: [], + MEDIAKEY: [], + SOURCEKEY: [], + CITATIONKEY: [], + REPOKEY: [], + NOTEKEY: [], + TAGKEY: [], + } #no custom callbacks to do self.custom_signal_keys = [] #set up callbacks to do nothing @@ -180,7 +180,7 @@ class CallbackManager: handles = ahandledict.get(key) if handles: self.__handles[key] = list( - set(self.__handles[key]).union(handles)) + set(self.__handles[key]).union(handles)) def unregister_handles(self, ahandledict): """ @@ -199,17 +199,17 @@ class CallbackManager: Unregister all handles that are registered """ self.__handles = { - PERSONKEY: [], - FAMILYKEY: [], - EVENTKEY: [], - PLACEKEY: [], - MEDIAKEY: [], - SOURCEKEY: [], - CITATIONKEY: [], - REPOKEY: [], - NOTEKEY: [], - TAGKEY: [], - } + PERSONKEY: [], + FAMILYKEY: [], + EVENTKEY: [], + PLACEKEY: [], + MEDIAKEY: [], + SOURCEKEY: [], + CITATIONKEY: [], + REPOKEY: [], + NOTEKEY: [], + TAGKEY: [], + } def register_callbacks(self, callbackdict): """ @@ -253,15 +253,12 @@ class CallbackManager: signal = key + method self.__do_unconnect(signal) self.__callbacks[signal][1] = self.database.connect( - signal, - self.__callbackcreator(signal)) + signal, self.__callbackcreator(signal)) for method in METHODS_NONE: signal = key + method self.__do_unconnect(signal) self.__callbacks[signal][1] = self.database.connect( - signal, - self.__callbackcreator(signal, - noarg=True)) + signal, self.__callbackcreator(signal, noarg=True)) def __do_callback(self, signal, *arg): """ @@ -304,7 +301,8 @@ class CallbackManager: managed automatically. """ if self.database: - self.custom_signal_keys.append(self.database.connect(name, callback)) + self.custom_signal_keys.append(self.database.connect(name, + callback)) def __callbackcreator(self, signal, noarg=False): """ @@ -338,17 +336,17 @@ def directhandledict(baseobj): Build a handledict from baseobj with all directly referenced objects """ handles = { - PERSONKEY: [], - FAMILYKEY: [], - EVENTKEY: [], - PLACEKEY: [], - MEDIAKEY: [], - SOURCEKEY: [], - CITATIONKEY: [], - REPOKEY: [], - NOTEKEY: [], - TAGKEY: [], - } + PERSONKEY: [], + FAMILYKEY: [], + EVENTKEY: [], + PLACEKEY: [], + MEDIAKEY: [], + SOURCEKEY: [], + CITATIONKEY: [], + REPOKEY: [], + NOTEKEY: [], + TAGKEY: [], + } for classn, handle in baseobj.get_referenced_handles(): handles[CLASS2KEY[classn]].append(handle) return handles @@ -359,17 +357,17 @@ def handledict(baseobj): referenced base obj that are present """ handles = { - PERSONKEY: [], - FAMILYKEY: [], - EVENTKEY: [], - PLACEKEY: [], - MEDIAKEY: [], - SOURCEKEY: [], - CITATIONKEY: [], - REPOKEY: [], - NOTEKEY: [], - TAGKEY: [], - } + PERSONKEY: [], + FAMILYKEY: [], + EVENTKEY: [], + PLACEKEY: [], + MEDIAKEY: [], + SOURCEKEY: [], + CITATIONKEY: [], + REPOKEY: [], + NOTEKEY: [], + TAGKEY: [], + } for classn, handle in baseobj.get_referenced_handles_recursively(): handles[CLASS2KEY[classn]].append(handle) return handles diff --git a/gramps/gen/utils/place.py b/gramps/gen/utils/place.py index de585c9de..6ead3601f 100644 --- a/gramps/gen/utils/place.py +++ b/gramps/gen/utils/place.py @@ -48,14 +48,14 @@ import math degrees = "1" North = _("%(north_latitude)s N") % {'north_latitude' : degrees} South = _("%(south_latitude)s S") % {'south_latitude' : degrees} -East = _("%(east_longitude)s E") % {'east_longitude' : degrees} -West = _("%(west_longitude)s W") % {'west_longitude' : degrees} +East = _("%(east_longitude)s E") % {'east_longitude' : degrees} +West = _("%(west_longitude)s W") % {'west_longitude' : degrees} # extract letters we really need -North = North.replace("1"," ").strip() -South = South.replace("1"," ").strip() -East = East.replace("1"," ").strip() -West = West.replace("1"," ").strip() +North = North.replace("1", " ").strip() +South = South.replace("1", " ").strip() +East = East.replace("1", " ").strip() +West = West.replace("1", " ").strip() # build dictionary with translation en to local language translate_en_loc = {} @@ -79,7 +79,7 @@ if 'N' == South or 'S' == North or 'E' == West or 'W' == East: # #------------------ -def __convert_structure_to_float(sign, degs, mins=0, secs=0.0) : +def __convert_structure_to_float(sign, degs, mins=0, secs=0.0): """helper function which converts a structure to a nice representation """ @@ -94,29 +94,29 @@ def __convert_using_float_repr(stringValue): """ helper function that tries to convert the string using the float representation """ - try : + try: v = float(stringValue) return v - except ValueError : - return None; + except ValueError: + return None def __convert_using_colon_repr(stringValue): """ helper function that tries to convert the string using the colon representation """ - if stringValue.find(r':') == -1 : + if stringValue.find(r':') == -1: return None l = stringValue.split(':') if len(l) < 2 or len(l) > 3: return None - l[0]=l[0].strip() + l[0] = l[0].strip() # if no characters before ':' nothing useful is input! if len(l[0]) == 0: return None if l[0][0] in ['+', '-']: sign = l[0][0] - l[0]=l[0][1:].strip() + l[0] = l[0][1:].strip() # regard a second sign as an error if l[0][0] in ['+', '-']: return None @@ -134,7 +134,7 @@ def __convert_using_colon_repr(stringValue): return None except: return None - secs=0. + secs = 0. if len(l) == 3: try: secs = float(l[2]) @@ -153,16 +153,16 @@ def __convert_using_classic_repr(stringValue, typedeg): return None # not a valid lat or lon #exchange some characters - stringValue = stringValue.replace('°',r'_') + stringValue = stringValue.replace('°', r'_') #allow to input ° as #, UTF-8 code c2b00a - stringValue = stringValue.replace('º',r'_') - #allow to input º as #, UTF-8 code c2ba0a - stringValue = stringValue.replace(r'#',r'_') + stringValue = stringValue.replace('º', r'_') + #allow to input º as #, UTF-8 code c2b a0a + stringValue = stringValue.replace(r'#', r'_') #allow to input " as '' - stringValue = stringValue.replace(r"''",r'"') + stringValue = stringValue.replace(r"''", r'"') #allow some special unicode symbols - stringValue = stringValue.replace('\u2033',r'"') - stringValue = stringValue.replace('\u2032',r"'") + stringValue = stringValue.replace('\u2033', r'"') + stringValue = stringValue.replace('\u2032', r"'") #ignore spaces, a regex with \s* would be better here... stringValue = stringValue.replace(r' ', r'') stringValue = stringValue.replace(r'\t', r'') @@ -193,9 +193,9 @@ def __convert_using_classic_repr(stringValue, typedeg): l2[0] = l4[0] # Convert the decimal part of minutes to seconds try: - lsecs=float('0.' + l4[1]) * 60.0 - # Set the seconds followed by direction letter N/S/W/E - l2[1] = str(lsecs) + '"' + l2[1] + lsecs = float('0.' + l4[1]) * 60.0 + # Set the seconds followed by direction letter N/S/W/E + l2[1] = str(lsecs) + '"' + l2[1] except: return None @@ -269,13 +269,13 @@ def __convert_using_modgedcom_repr(val, typedeg): stringValue = '-' + val[:pos] else: return None - try : + try: v = float(stringValue) return v - except ValueError : - return None; + except ValueError: + return None -def __convert_float_val(val, typedeg = "lat"): +def __convert_float_val(val, typedeg="lat"): # function converting input to float, recognizing decimal input, or # degree notation input. Only english input # There is no check on maximum/minimum of degree @@ -287,7 +287,7 @@ def __convert_float_val(val, typedeg = "lat"): #this is no problem, as a number like 100,000.20 cannot appear in #lat/lon #change XX,YY into XX.YY - if val.find(r'.') == -1 : + if val.find(r'.') == -1: val = val.replace(',', '.') # format: XX.YYYY @@ -297,17 +297,17 @@ def __convert_float_val(val, typedeg = "lat"): # format: XX:YY:ZZ v = __convert_using_colon_repr(val) - if v is not None : + if v is not None: return v # format: XX° YY' ZZ" [NSWE] v = __convert_using_classic_repr(val, typedeg) - if v is not None : + if v is not None: return v # format XX.YYYY[NSWE] v = __convert_using_modgedcom_repr(val, typedeg) - if v is not None : + if v is not None: return v # no format succeeded @@ -365,12 +365,12 @@ def conv_lat_lon(latitude, longitude, format="D.D4"): # we start the function changing latitude/longitude in english if latitude.find('N') == -1 and latitude.find('S') == -1: # entry is not in english, convert to english - latitude = latitude.replace(translate_en_loc['N'],'N') - latitude = latitude.replace(translate_en_loc['S'],'S') + latitude = latitude.replace(translate_en_loc['N'], 'N') + latitude = latitude.replace(translate_en_loc['S'], 'S') if longitude.find('E') == -1 and longitude.find('W') == -1: # entry is not in english, convert to english - longitude = longitude.replace(translate_en_loc['W'],'W') - longitude = longitude.replace(translate_en_loc['E'],'E') + longitude = longitude.replace(translate_en_loc['W'], 'W') + longitude = longitude.replace(translate_en_loc['E'], 'E') # take away leading spaces latitude = latitude.lstrip() @@ -383,7 +383,7 @@ def conv_lat_lon(latitude, longitude, format="D.D4"): longitude = longitude[1:] + longitude[0] # convert to float - lat_float = __convert_float_val(latitude, 'lat') + lat_float = __convert_float_val(latitude, 'lat') lon_float = __convert_float_val(longitude, 'lon') # give output (localized if needed) @@ -403,19 +403,19 @@ def conv_lat_lon(latitude, longitude, format="D.D4"): # correct possible roundoff error str_lon = "%.4f" % (lon_float) if str_lon == "180.0000": - str_lon ="-180.0000" - return ("%.4f" % lat_float , str_lon) + str_lon = "-180.0000" + return ("%.4f" % lat_float, str_lon) if format == "D.D8" or format == "RT90": # correct possible roundoff error str_lon = "%.8f" % (lon_float) if str_lon == "180.00000000": - str_lon ="-180.00000000" + str_lon = "-180.00000000" if format == "RT90": tx = __conv_WGS84_SWED_RT90(lat_float, lon_float) return ("%i" % tx[0], "%i" % tx[1]) else: - return ("%.8f" % lat_float , str_lon) + return ("%.8f" % lat_float, str_lon) if format == "GEDCOM": # The 5.5.1 spec is inconsistent. Length is supposedly 5 to 8 chars, @@ -426,20 +426,21 @@ def conv_lat_lon(latitude, longitude, format="D.D4"): if lon_float >= 0: str_lon = "%.6f" % (lon_float) if str_lon == "180.000000": - str_lon ="W180.000000" + str_lon = "W180.000000" else: str_lon = "E" + str_lon else: str_lon = "W" + "%.6f" % (-lon_float) str_lon = str_lon[:-5] + str_lon[-5:].rstrip("0") - str_lat = ("%s%.6f" % (("N", lat_float) if lat_float >= 0 else ("S", -lat_float))) + str_lat = ("%s%.6f" % (("N", lat_float) if lat_float >= 0 + else ("S", -lat_float))) str_lat = str_lat[:-5] + str_lat[-5:].rstrip("0") return (str_lat, str_lon) deg_lat = int(lat_float) deg_lon = int(lon_float) - min_lat = int(60. * (lat_float - float(deg_lat) )) - min_lon = int(60. * (lon_float - float(deg_lon) )) + min_lat = int(60. * (lat_float - float(deg_lat))) + min_lon = int(60. * (lon_float - float(deg_lon))) sec_lat = 3600. * (lat_float - float(deg_lat) - float(min_lat) / 60.) sec_lon = 3600. * (lon_float - float(deg_lon) - float(min_lon) / 60.) @@ -463,14 +464,14 @@ def conv_lat_lon(latitude, longitude, format="D.D4"): dir_lat = translate_en_loc['N'] else: dir_lat = translate_en_loc['S'] - sign_lat= "-" - sign_lon= "+" + sign_lat = "-" + sign_lon = "+" dir_lon = "" if lon_float >= 0.: dir_lon = translate_en_loc['E'] else: dir_lon = translate_en_loc['W'] - sign_lon= "-" + sign_lon = "-" if format == "DEG": str_lat = ("%d°%02d'%05.2f\"" % (deg_lat, min_lat, sec_lat)) + dir_lat @@ -497,10 +498,10 @@ def conv_lat_lon(latitude, longitude, format="D.D4"): return (str_lat, str_lon) if format == "DEG-:": - if sign_lat=="+": + if sign_lat == "+": sign_lat = "" sign_lon_h = sign_lon - if sign_lon=="+": + if sign_lon == "+": sign_lon_h = "" str_lat = sign_lat + ("%d:%02d:%05.2f" % (deg_lat, min_lat, sec_lat)) str_lon = sign_lon_h + ("%d:%02d:%05.2f" % (deg_lon, min_lon, sec_lon)) @@ -598,7 +599,7 @@ def __conv_WGS84_SWED_RT90(lat, lon): L0 = math.radians(15.8062845294) # 15 deg 48 min 22.624306 sec k0 = 1.00000561024 a = 6378137.0 # meter - at = a/(1.0+n)*(1.0+ 1.0/4.0* pow(n,2)+1.0/64.0*pow(n,4)) + at = a/(1.0+n)*(1.0+ 1.0/4.0* pow(n, 2)+1.0/64.0*pow(n, 4)) FN = -667.711 # m FE = 1500064.274 # m @@ -606,20 +607,21 @@ def __conv_WGS84_SWED_RT90(lat, lon): lat_rad = math.radians(lat) lon_rad = math.radians(lon) A = e2 - B = 1.0/6.0*(5.0*pow(e2,2) - pow(e2,3)) - C = 1.0/120.0*(104.0*pow(e2,3) - 45.0*pow(e2,4)) - D = 1.0/1260.0*(1237.0*pow(e2,4)) + B = 1.0/6.0*(5.0*pow(e2, 2) - pow(e2, 3)) + C = 1.0/120.0*(104.0*pow(e2, 3) - 45.0*pow(e2, 4)) + D = 1.0/1260.0*(1237.0*pow(e2, 4)) DL = lon_rad - L0 - E = A + B*pow(math.sin(lat_rad),2) + \ - C*pow(math.sin(lat_rad),4) + \ - D*pow(math.sin(lat_rad),6) + E = A + B*pow(math.sin(lat_rad), 2) + \ + C*pow(math.sin(lat_rad), 4) + \ + D*pow(math.sin(lat_rad), 6) psi = lat_rad - math.sin(lat_rad)*math.cos(lat_rad)*E - xi = math.atan2(math.tan(psi),math.cos(DL)) + xi = math.atan2(math.tan(psi), math.cos(DL)) eta = atanh(math.cos(psi)*math.sin(DL)) - B1 = 1.0/2.0*n - 2.0/3.0*pow(n,2) + 5.0/16.0*pow(n,3) + 41.0/180.0*pow(n,4) - B2 = 13.0/48.0*pow(n,2) - 3.0/5.0*pow(n,3) + 557.0/1440.0*pow(n,4) - B3 = 61.0/240.0*pow(n,3) - 103.0/140.0*pow(n,4) - B4 = 49561.0/161280.0*pow(n,4) + B1 = 1.0/2.0*n - 2.0/3.0*pow(n, 2) + 5.0/16.0*pow(n, 3) + \ + 41.0/180.0*pow(n, 4) + B2 = 13.0/48.0*pow(n, 2) - 3.0/5.0*pow(n, 3) + 557.0/1440.0*pow(n, 4) + B3 = 61.0/240.0*pow(n, 3) - 103.0/140.0*pow(n, 4) + B4 = 49561.0/161280.0*pow(n, 4) X = xi + B1*math.sin(2.0*xi)*math.cosh(2.0*eta) + \ B2*math.sin(4.0*xi)*math.cosh(4.0*eta) + \ B3*math.sin(6.0*xi)*math.cosh(6.0*eta) + \ @@ -644,16 +646,17 @@ def __conv_SWED_RT90_WGS84(X, Y): L0 = math.radians(15.8062845294) # 15 deg 48 min 22.624306 sec k0 = 1.00000561024 a = 6378137.0 # meter - at = a/(1.0+n)*(1.0+ 1.0/4.0* pow(n,2)+1.0/64.0*pow(n,4)) + at = a/(1.0+n)*(1.0+ 1.0/4.0* pow(n, 2)+1.0/64.0*pow(n, 4)) FN = -667.711 # m FE = 1500064.274 # m xi = (X - FN)/(k0*at) eta = (Y - FE)/(k0*at) - D1 = 1.0/2.0*n - 2.0/3.0*pow(n,2) + 37.0/96.0*pow(n,3) - 1.0/360.0*pow(n,4) - D2 = 1.0/48.0*pow(n,2) + 1.0/15.0*pow(n,3) - 437.0/1440.0*pow(n,4) - D3 = 17.0/480.0*pow(n,3) - 37.0/840.0*pow(n,4) - D4 = 4397.0/161280.0*pow(n,4) + D1 = 1.0/2.0*n - 2.0/3.0*pow(n, 2) + 37.0/96.0*pow(n, 3) - \ + 1.0/360.0*pow(n, 4) + D2 = 1.0/48.0*pow(n, 2) + 1.0/15.0*pow(n, 3) - 437.0/1440.0*pow(n, 4) + D3 = 17.0/480.0*pow(n, 3) - 37.0/840.0*pow(n, 4) + D4 = 4397.0/161280.0*pow(n, 4) xip = xi - D1*math.sin(2.0*xi)*math.cosh(2.0*eta) - \ D2*math.sin(4.0*xi)*math.cosh(4.0*eta) - \ D3*math.sin(6.0*xi)*math.cosh(6.0*eta) - \ @@ -663,15 +666,15 @@ def __conv_SWED_RT90_WGS84(X, Y): D3*math.cos(6.0*xi)*math.sinh(6.0*eta) - \ D4*math.cos(8.0*xi)*math.sinh(8.0*eta) psi = math.asin(math.sin(xip)/math.cosh(etap)) - DL = math.atan2(math.sinh(etap),math.cos(xip)) + DL = math.atan2(math.sinh(etap), math.cos(xip)) LON = L0 + DL - A = e2 + pow(e2,2) + pow(e2,3) + pow(e2,4) - B = -1.0/6.0*(7.0*pow(e2,2) + 17*pow(e2,3) + 30*pow(e2,4)) - C = 1.0/120.0*(224.0*pow(e2,3) + 889.0*pow(e2,4)) - D = 1.0/1260.0*(4279.0*pow(e2,4)) - E = A + B*pow(math.sin(psi),2) + \ - C*pow(math.sin(psi),4) + \ - D*pow(math.sin(psi),6) + A = e2 + pow(e2, 2) + pow(e2, 3) + pow(e2, 4) + B = -1.0/6.0*(7.0*pow(e2, 2) + 17*pow(e2, 3) + 30*pow(e2, 4)) + C = 1.0/120.0*(224.0*pow(e2, 3) + 889.0*pow(e2, 4)) + D = 1.0/1260.0*(4279.0*pow(e2, 4)) + E = A + B*pow(math.sin(psi), 2) + \ + C*pow(math.sin(psi), 4) + \ + D*pow(math.sin(psi), 6) LAT = psi + math.sin(psi)*math.cos(psi)*E LAT = math.degrees(LAT) LON = math.degrees(LON) @@ -686,7 +689,7 @@ def __conv_SWED_RT90_WGS84(X, Y): #------------------------------------------------------------------------- if __name__ == '__main__': - def test_formats_success(lat1,lon1, text=''): + def test_formats_success(lat1, lon1, text=''): format0 = "D.D4" format1 = "D.D8" format2 = "DEG" @@ -697,29 +700,29 @@ if __name__ == '__main__': format7 = "RT90" format8 = "GEDCOM" print("Testing conv_lat_lon function, "+text+':') - res1, res2 = conv_lat_lon(lat1,lon1,format0) - print(lat1,lon1,"in format",format0, "is ",res1,res2) - res1, res2 = conv_lat_lon(lat1,lon1,format1) - print(lat1,lon1,"in format",format1, "is ",res1,res2) - res1, res2 = conv_lat_lon(lat1,lon1,format2) - print(lat1,lon1,"in format",format2, "is ",res1,res2) - res1, res2 = conv_lat_lon(lat1,lon1,format3) - print(lat1,lon1,"in format",format3, "is ",res1,res2) - res = conv_lat_lon(lat1,lon1,format4) - print(lat1,lon1,"in format",format4, "is ",res) - res = conv_lat_lon(lat1,lon1,format5) - print(lat1,lon1,"in format",format5, "is",res) - res = conv_lat_lon(lat1,lon1,format6) - print(lat1,lon1,"in format",format6, "is",res) - res1, res2 = conv_lat_lon(lat1,lon1,format7) - print(lat1,lon1,"in format",format7, "is",res1,res2,"\n") - res1, res2 = conv_lat_lon(lat1,lon1,format8) - print(lat1,lon1,"in format",format8, "is",res1,res2,"\n") + res1, res2 = conv_lat_lon(lat1, lon1, format0) + print(lat1, lon1, "in format", format0, "is ", res1, res2) + res1, res2 = conv_lat_lon(lat1, lon1, format1) + print(lat1, lon1, "in format", format1, "is ", res1, res2) + res1, res2 = conv_lat_lon(lat1, lon1, format2) + print(lat1, lon1, "in format", format2, "is ", res1, res2) + res1, res2 = conv_lat_lon(lat1, lon1, format3) + print(lat1, lon1, "in format", format3, "is ", res1, res2) + res = conv_lat_lon(lat1, lon1, format4) + print(lat1, lon1, "in format", format4, "is ", res) + res = conv_lat_lon(lat1, lon1, format5) + print(lat1, lon1, "in format", format5, "is", res) + res = conv_lat_lon(lat1, lon1, format6) + print(lat1, lon1, "in format", format6, "is", res) + res1, res2 = conv_lat_lon(lat1, lon1, format7) + print(lat1, lon1, "in format", format7, "is", res1, res2, "\n") + res1, res2 = conv_lat_lon(lat1, lon1, format8) + print(lat1, lon1, "in format", format8, "is", res1, res2, "\n") - def test_formats_fail(lat1,lon1,text=''): + def test_formats_fail(lat1, lon1, text=''): print("This test should make conv_lat_lon function fail, "+text+":") - res1, res2 = conv_lat_lon(lat1,lon1) - print(lat1,lon1," fails to convert, result=", res1,res2,"\n") + res1, res2 = conv_lat_lon(lat1, lon1) + print(lat1, lon1, " fails to convert, result=", res1, res2, "\n") def test_RT90_conversion(): """ @@ -728,128 +731,130 @@ if __name__ == '__main__': la = 59.0 + 40.0/60. + 9.09/3600.0 lo = 12.0 + 58.0/60.0 + 57.74/3600.0 x, y = __conv_WGS84_SWED_RT90(la, lo) - lanew, lonew = __conv_SWED_RT90_WGS84(x,y) + lanew, lonew = __conv_SWED_RT90_WGS84(x, y) assert math.fabs(lanew - la) < 1e-6, math.fabs(lanew - la) assert math.fabs(lonew - lo) < 1e-6, math.fabs(lonew - lo) lat, lon = '50.849888888888', '2.885897222222' - test_formats_success(lat,lon) + test_formats_success(lat, lon) lat, lon = ' 50°50\'59.60"N', ' 2°53\'9.23"E' - test_formats_success(lat,lon) + test_formats_success(lat, lon) lat, lon = ' 50 : 50 : 59.60 ', ' -2:53 : 9.23 ' - test_formats_success(lat,lon) + test_formats_success(lat, lon) lat, lon = ' dummy', ' 2#53 \' 9.23 " E ' - test_formats_fail(lat,lon) + test_formats_fail(lat, lon) lat, lon = ' 50:50: 59.60', ' d u m my' - test_formats_fail(lat,lon) - lat, lon = ' 50°59.60"N', ' 2°53\'E' - test_formats_success(lat,lon) - lat, lon = ' 11° 11\' 11" N, 11° 11\' 11" O', ' ' - test_formats_fail(lat,lon) + test_formats_fail(lat, lon) + lat, lon = ' 50°59.60"N', ' 2°53\'E' + test_formats_success(lat, lon) + lat, lon = ' 11° 11\' 11" N, 11° 11\' 11" O', ' ' + test_formats_fail(lat, lon) # very small negative - lat, lon = '-0.00006', '-0.00006' - test_formats_success(lat,lon) + lat, lon = '-0.00006', '-0.00006' + test_formats_success(lat, lon) # missing direction N/S - lat, lon = ' 50°59.60"', ' 2°53\'E' - test_formats_fail(lat,lon) + lat, lon = ' 50°59.60"', ' 2°53\'E' + test_formats_fail(lat, lon) # wrong direction on latitude - lat, lon = ' 50°59.60"E', ' 2°53\'N' - test_formats_fail(lat,lon) + lat, lon = ' 50°59.60"E', ' 2°53\'N' + test_formats_fail(lat, lon) # same as above - lat, lon = ' 50°59.99"E', ' 2°59\'59.99"N' - test_formats_fail(lat,lon) + lat, lon = ' 50°59.99"E', ' 2°59\'59.99"N' + test_formats_fail(lat, lon) # test precision - lat, lon = ' 50°59.99"S', ' 2°59\'59.99"E' - test_formats_success(lat,lon) + lat, lon = ' 50°59.99"S', ' 2°59\'59.99"E' + test_formats_success(lat, lon) lat, lon = 'N50.849888888888', 'E2.885897222222' - test_formats_success(lat,lon) + test_formats_success(lat, lon) # to large value of lat - lat, lon = '90.849888888888', '2.885897222222' - test_formats_fail(lat,lon) + lat, lon = '90.849888888888', '2.885897222222' + test_formats_fail(lat, lon) # extreme values allowed - lat, lon = '90', '-180' - test_formats_success(lat,lon) + lat, lon = '90', '-180' + test_formats_success(lat, lon) # extreme values allowed - lat, lon = '90° 00\' 00.00" S ', '179° 59\'59.99"W' - test_formats_success(lat,lon) + lat, lon = '90° 00\' 00.00" S ', '179° 59\'59.99"W' + test_formats_success(lat, lon) # extreme value not allowed - lat, lon = '90° 00\' 00.00" N', '180° 00\'00.00" E' - test_formats_fail(lat,lon) + lat, lon = '90° 00\' 00.00" N', '180° 00\'00.00" E' + test_formats_fail(lat, lon) # extreme values allowed - lat, lon = '90: 00: 00.00 ', '-179: 59:59.99' - test_formats_success(lat,lon) + lat, lon = '90: 00: 00.00 ', '-179: 59:59.99' + test_formats_success(lat, lon) # extreme value not allowed - lat, lon = '90° 00\' 00.00" N', '180:00:00.00' - test_formats_fail(lat,lon) + lat, lon = '90° 00\' 00.00" N', '180:00:00.00' + test_formats_fail(lat, lon) # extreme values not allowed - lat, lon = '90', '180' - test_formats_fail(lat,lon) - lat, lon = ' 89°59\'60"N', ' 2°53\'W' - test_formats_fail(lat,lon) - lat, lon = ' 89°60\'00"N', ' 2°53\'W' - test_formats_fail(lat,lon) - lat, lon = ' 89.1°40\'00"N', ' 2°53\'W' - test_formats_fail(lat,lon) - lat, lon = ' 89°40\'00"N', ' 2°53.1\'W' - test_formats_fail(lat,lon) - lat, lon = '0', '0' - test_formats_success(lat,lon, - "Special 0 value, crossing 0-meridian and equator") + lat, lon = '90', '180' + test_formats_fail(lat, lon) + lat, lon = ' 89°59\'60"N', ' 2°53\'W' + test_formats_fail(lat, lon) + lat, lon = ' 89°60\'00"N', ' 2°53\'W' + test_formats_fail(lat, lon) + lat, lon = ' 89.1°40\'00"N', ' 2°53\'W' + test_formats_fail(lat, lon) + lat, lon = ' 89°40\'00"N', ' 2°53.1\'W' + test_formats_fail(lat, lon) + lat, lon = '0', '0' + test_formats_success(lat, lon, + "Special 0 value, crossing 0-meridian and equator") # small values close to equator - lat, lon = ' 1°1"N', ' 1°1\'E' - test_formats_success(lat,lon) + lat, lon = ' 1°1"N', ' 1°1\'E' + test_formats_success(lat, lon) # roundoff - lat, lon = ' 1°59.999"N', ' 1°59.999"E' - test_formats_success(lat,lon,'Examples of round off and how it behaves') - lat, lon = ' 1°59\'59.9999"N', ' 1°59\'59.9999"E' - test_formats_success(lat,lon,'Examples of round off and how it behaves') - lat, lon = '89°59\'59.9999"S', '179°59\'59.9999"W' - test_formats_success(lat,lon,'Examples of round off and how it behaves') - lat, lon = '89°59\'59.9999"N', '179°59\'59.9999"E' - test_formats_success(lat,lon,'Examples of round off and how it behaves') + lat, lon = ' 1°59.999"N', ' 1°59.999"E' + test_formats_success(lat, lon, 'Examples of round off and how it behaves') + lat, lon = ' 1°59\'59.9999"N', ' 1°59\'59.9999"E' + test_formats_success(lat, lon, 'Examples of round off and how it behaves') + lat, lon = '89°59\'59.9999"S', '179°59\'59.9999"W' + test_formats_success(lat, lon, 'Examples of round off and how it behaves') + lat, lon = '89°59\'59.9999"N', '179°59\'59.9999"E' + test_formats_success(lat, lon, 'Examples of round off and how it behaves') #insane number of decimals: - lat, lon = '89°59\'59.99999999"N', '179°59\'59.99999999"E' - test_formats_success(lat,lon,'Examples of round off and how it begaves') + lat, lon = '89°59\'59.99999999"N', '179°59\'59.99999999"E' + test_formats_success(lat, lon, 'Examples of round off and how it begaves') #recognise '' as seconds " - lat, lon = '89°59\'59.99\'\' N', '179°59\'59.99\'\'E' - test_formats_success(lat,lon, "input \" as ''") + lat, lon = '89°59\'59.99\'\' N', '179°59\'59.99\'\'E' + test_formats_success(lat, lon, "input \" as ''") #test localisation of , and . as delimiter lat, lon = '50.849888888888', '2,885897222222' - test_formats_success(lat,lon, 'localisation of . and , ') - lat, lon = '89°59\'59.9999"S', '179°59\'59,9999"W' - test_formats_success(lat,lon, 'localisation of . and , ') - lat, lon = '89°59\'1.599,999"S', '179°59\'59,9999"W' - test_formats_fail(lat,lon, 'localisation of . and , ') + test_formats_success(lat, lon, 'localisation of . and , ') + lat, lon = '89°59\'59.9999"S', '179°59\'59,9999"W' + test_formats_success(lat, lon, 'localisation of . and , ') + lat, lon = '89°59\'1.599,999"S', '179°59\'59,9999"W' + test_formats_fail(lat, lon, 'localisation of . and , ') #rest - lat, lon = '81.2', '-182.3' - test_formats_fail(lat,lon) - lat, lon = '-91.2', '-1' - test_formats_fail(lat,lon) - lat, lon = '++50:10:1', '2:1:2' - test_formats_fail(lat,lon) - lat, lon = '-50:10:1', '-+2:1:2' - test_formats_success(lat,lon) - lat, lon = '-50::1', '-2:1:2' - test_formats_fail(lat,lon) - lat, lon = '- 50 : 2 : 1 ', '-2:1:2' - test_formats_success(lat,lon) - lat, lon = '+ 50:2 : 1', '-2:1:2' - test_formats_success(lat,lon) - lat, lon = '+50:', '-2:1:2' - test_formats_fail(lat,lon) - lat, lon = '+50:1', '-2:1:2' - test_formats_success(lat,lon) - lat, lon = '+50: 0 : 1 : 1', '-2:1:2' - test_formats_fail(lat,lon) + lat, lon = '81.2', '-182.3' + test_formats_fail(lat, lon) + lat, lon = '-91.2', '-1' + test_formats_fail(lat, lon) + lat, lon = '++50:10:1', '2:1:2' + test_formats_fail(lat, lon) + lat, lon = '-50:10:1', '-+2:1:2' + test_formats_success(lat, lon) + lat, lon = '-50::1', '-2:1:2' + test_formats_fail(lat, lon) + lat, lon = '- 50 : 2 : 1 ', '-2:1:2' + test_formats_success(lat, lon) + lat, lon = '+ 50:2 : 1', '-2:1:2' + test_formats_success(lat, lon) + lat, lon = '+50:', '-2:1:2' + test_formats_fail(lat, lon) + lat, lon = '+50:1', '-2:1:2' + test_formats_success(lat, lon) + lat, lon = '+50: 0 : 1 : 1', '-2:1:2' + test_formats_fail(lat, lon) lat, lon = '+61° 43\' 60.00"', '+17° 7\' 60.00"' - test_formats_fail(lat,lon) + test_formats_fail(lat, lon) lat, lon = '+61° 44\' 00.00"N', '+17° 8\' 00.00"E' - test_formats_success(lat,lon) - lat, lon = ': 0 : 1 : 1', ':1:2' - test_formats_fail(lat,lon) + test_formats_success(lat, lon) + lat, lon = ': 0 : 1 : 1', ':1:2' + test_formats_fail(lat, lon) lat, lon = 'N 50º52\'21.92"', 'E 124º52\'21.92"' - test_formats_success(lat,lon, 'New format with N/E first and another º - character') + test_formats_success(lat, lon, + 'New format with N/E first and another º - character') lat, lon = 'S 50º52\'21.92"', 'W 124º52\'21.92"' - test_formats_success(lat,lon, 'New format with S/W first and another º - character') + test_formats_success(lat, lon, + 'New format with S/W first and another º - character') test_RT90_conversion() diff --git a/gramps/gen/utils/string.py b/gramps/gen/utils/string.py index 68231030b..575d71190 100644 --- a/gramps/gen/utils/string.py +++ b/gramps/gen/utils/string.py @@ -48,7 +48,7 @@ gender = { Person.UNKNOWN : _("gender|unknown"), } -def format_gender( type): +def format_gender(type): return gender.get(type[0], _("Invalid")) conf_strings = { @@ -63,16 +63,16 @@ conf_strings = { family_rel_descriptions = { FamilyRelType.MARRIED : _("A legal or common-law relationship " - "between a husband and wife"), + "between a husband and wife"), FamilyRelType.UNMARRIED : _("No legal or common-law relationship " - "between man and woman"), + "between man and woman"), FamilyRelType.CIVIL_UNION : _("An established relationship between " - "members of the same sex"), + "members of the same sex"), FamilyRelType.UNKNOWN : _("Unknown relationship between a man " - "and woman"), + "and woman"), FamilyRelType.CUSTOM : _("An unspecified relationship between " - "a man and woman"), + "a man and woman"), } data_recover_msg = _('The data can only be recovered by Undo operation ' - 'or by quitting with abandoning changes.') + 'or by quitting with abandoning changes.') From 7649f03c7004b25c5144d13b3dfe62f13fbd4b6a Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Wed, 25 May 2016 12:39:48 -0400 Subject: [PATCH 03/11] CacheProxyDb: adds LRU cache for handle lookups --- gramps/gen/proxy/__init__.py | 1 + gramps/gen/proxy/cache.py | 182 +++++++++++++++++++++++ gramps/plugins/webreport/narrativeweb.py | 4 +- 3 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 gramps/gen/proxy/cache.py diff --git a/gramps/gen/proxy/__init__.py b/gramps/gen/proxy/__init__.py index b52164b42..e471cbe4b 100644 --- a/gramps/gen/proxy/__init__.py +++ b/gramps/gen/proxy/__init__.py @@ -26,3 +26,4 @@ from .filter import FilterProxyDb from .living import LivingProxyDb from .private import PrivateProxyDb from .referencedbyselection import ReferencedBySelectionProxyDb +from .cache import CacheProxyDb diff --git a/gramps/gen/proxy/cache.py b/gramps/gen/proxy/cache.py new file mode 100644 index 000000000..3bc2db8b5 --- /dev/null +++ b/gramps/gen/proxy/cache.py @@ -0,0 +1,182 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (c) 2016 Gramps Development Team +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +Proxy class for the Gramps databases. Caches lookups from handles. +""" + +class CacheProxyDb: + """ + A Proxy for a database with cached lookups on handles. + + Does not invalid caches. Should be used only in read-only + places, and not where caches are altered. + """ + def __init__(self, database): + """ + CacheProxy will cache items based on their handle. + + Assumes all handles (regardless of type) are unique. + Database is called self.db for consistancy with other + proxies. + """ + self.db = database + self.clear_cache() + + def __getattr__(self, attr): + """ + If an attribute isn't found here, use the self.db + version. + """ + return self.db.__getattr__(attr) + + def clear_cache(self, handle=None): + """ + Clears all caches if handle is None, or + specific entry. + """ + from gramps.gui.views.treemodels.lru import LRU + if handle: + del self.cache_handle[handle] + else: + self.cache_handle = LRU(100000) + + def get_person_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_person_from_handle(handle) + return self.cache_handle[handle] + + def get_event_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_event_from_handle(handle) + return self.cache_handle[handle] + + def get_family_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_family_from_handle(handle) + return self.cache_handle[handle] + + def get_repository_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_repository_from_handle(handle) + return self.cache_handle[handle] + + def get_place_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_place_from_handle(handle) + return self.cache_handle[handle] + + def get_place_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_place_from_handle(handle) + return self.cache_handle[handle] + + def get_citation_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_citation_from_handle(handle) + return self.cache_handle[handle] + + def get_source_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_source_from_handle(handle) + return self.cache_handle[handle] + + def get_note_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_note_from_handle(handle) + return self.cache_handle[handle] + + def get_media_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_media_from_handle(handle) + return self.cache_handle[handle] + + def get_tag_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_tag_from_handle(handle) + return self.cache_handle[handle] + + diff --git a/gramps/plugins/webreport/narrativeweb.py b/gramps/plugins/webreport/narrativeweb.py index 040302938..0388961d8 100644 --- a/gramps/plugins/webreport/narrativeweb.py +++ b/gramps/plugins/webreport/narrativeweb.py @@ -125,7 +125,7 @@ from gramps.gen.utils.image import image_size # , resize_to_jpeg_buffer from gramps.gen.display.name import displayer as _nd from gramps.gen.display.place import displayer as _pd from gramps.gen.datehandler import displayer as _dd -from gramps.gen.proxy import LivingProxyDb +from gramps.gen.proxy import LivingProxyDb, CacheProxyDb from gramps.plugins.lib.libhtmlconst import _CHARACTER_SETS, _CC, _COPY_OPTIONS from gramps.gen.datehandler import get_date @@ -7990,6 +7990,8 @@ class NavWebReport(Report): None, yearsafterdeath) + self.database = CacheProxyDb(self.database) + filters_option = menu.get_option_by_name('filter') self.filter = filters_option.get_filter() From 758d63c0fa0fc467088e4fe6312417aeba2c1e7b Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Wed, 25 May 2016 12:56:33 -0400 Subject: [PATCH 04/11] Remove trailing whitespace --- gramps/gen/proxy/cache.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/gramps/gen/proxy/cache.py b/gramps/gen/proxy/cache.py index 3bc2db8b5..88d92c391 100644 --- a/gramps/gen/proxy/cache.py +++ b/gramps/gen/proxy/cache.py @@ -178,5 +178,3 @@ class CacheProxyDb: if handle not in self.cache_handle: self.cache_handle[handle] = self.db.get_tag_from_handle(handle) return self.cache_handle[handle] - - From 3af7ff4e9b0cba263e7e03ac10ae12841d7a86b4 Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Wed, 25 May 2016 14:41:07 -0400 Subject: [PATCH 05/11] Spelling error --- gramps/gen/proxy/cache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gramps/gen/proxy/cache.py b/gramps/gen/proxy/cache.py index 88d92c391..559ed504d 100644 --- a/gramps/gen/proxy/cache.py +++ b/gramps/gen/proxy/cache.py @@ -34,7 +34,7 @@ class CacheProxyDb: CacheProxy will cache items based on their handle. Assumes all handles (regardless of type) are unique. - Database is called self.db for consistancy with other + Database is called self.db for consistency with other proxies. """ self.db = database From ffd58ccd9ff2ec47f6c12fdc849a1cb779933ad8 Mon Sep 17 00:00:00 2001 From: Paul Franklin Date: Wed, 25 May 2016 12:29:44 -0700 Subject: [PATCH 06/11] increase pylint score of fanchart report from 4.47 to 9.40 --- gramps/plugins/drawreport/fanchart.py | 513 ++++++++++++++------------ 1 file changed, 268 insertions(+), 245 deletions(-) diff --git a/gramps/plugins/drawreport/fanchart.py b/gramps/plugins/drawreport/fanchart.py index c37bd0139..515c9a288 100644 --- a/gramps/plugins/drawreport/fanchart.py +++ b/gramps/plugins/drawreport/fanchart.py @@ -23,6 +23,8 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +""" fanchart report """ + #------------------------------------------------------------------------ # # python modules @@ -67,25 +69,22 @@ HALF_CIRCLE = 1 QUAR_CIRCLE = 2 BACKGROUND_WHITE = 0 -BACKGROUND_GEN = 1 +BACKGROUND_GEN = 1 -RADIAL_UPRIGHT = 0 +RADIAL_UPRIGHT = 0 RADIAL_ROUNDABOUT = 1 # minor offset just usefull for generation 11, # to not a bit offset between the text and the polygon # this can be considered as a bad hack WEDGE_TEXT_BARRE_OFFSET = 0.0016 -pt2cm = utils.pt2cm - -cal = config.get('preferences.calendar-format-report') #------------------------------------------------------------------------ # # private functions # #------------------------------------------------------------------------ -def draw_wedge(doc, style, centerx, centery, radius, start_angle, +def draw_wedge(doc, style, centerx, centery, radius, start_angle, end_angle, do_rendering, short_radius=0): """ Draw a wedge shape. @@ -93,7 +92,7 @@ def draw_wedge(doc, style, centerx, centery, radius, start_angle, while end_angle < start_angle: end_angle += 360 - p = [] + path = [] degreestoradians = pi / 180.0 radiansdelta = degreestoradians / 2 @@ -105,40 +104,40 @@ def draw_wedge(doc, style, centerx, centery, radius, start_angle, if short_radius == 0: if (end_angle - start_angle) != 360: - p.append((centerx, centery)) + path.append((centerx, centery)) else: origx = (centerx + cos(angle) * short_radius) origy = (centery + sin(angle) * short_radius) - p.append((origx, origy)) + path.append((origx, origy)) while angle < eangle: - x = centerx + cos(angle) * radius - y = centery + sin(angle) * radius - p.append((x, y)) + _x_ = centerx + cos(angle) * radius + _y_ = centery + sin(angle) * radius + path.append((_x_, _y_)) angle = angle + radiansdelta - x = centerx + cos(eangle) * radius - y = centery + sin(eangle) * radius - p.append((x, y)) + _x_ = centerx + cos(eangle) * radius + _y_ = centery + sin(eangle) * radius + path.append((_x_, _y_)) if short_radius: - x = centerx + cos(eangle) * short_radius - y = centery + sin(eangle) * short_radius - p.append((x, y)) + _x_ = centerx + cos(eangle) * short_radius + _y_ = centery + sin(eangle) * short_radius + path.append((_x_, _y_)) angle = eangle while angle >= sangle: - x = centerx + cos(angle) * short_radius - y = centery + sin(angle) * short_radius - p.append((x, y)) + _x_ = centerx + cos(angle) * short_radius + _y_ = centery + sin(angle) * short_radius + path.append((_x_, _y_)) angle -= radiansdelta if do_rendering: - doc.draw_path(style, p) + doc.draw_path(style, path) delta = (eangle - sangle) / 2.0 rad = short_radius + (radius - short_radius) / 2.0 - return ( (centerx + cos(sangle + delta + WEDGE_TEXT_BARRE_OFFSET) * rad), - (centery + sin(sangle + delta + WEDGE_TEXT_BARRE_OFFSET) * rad)) + return ((centerx + cos(sangle + delta + WEDGE_TEXT_BARRE_OFFSET) * rad), + (centery + sin(sangle + delta + WEDGE_TEXT_BARRE_OFFSET) * rad)) #------------------------------------------------------------------------ # @@ -182,19 +181,19 @@ class FanChart(Report): stdoptions.run_living_people_option(self, menu, rlocale) self.max_generations = menu.get_option_by_name('maxgen').get_value() - self.circle = menu.get_option_by_name('circle').get_value() - self.background = menu.get_option_by_name('background').get_value() - self.radial = menu.get_option_by_name('radial').get_value() - pid = menu.get_option_by_name('pid').get_value() - self.draw_empty = menu.get_option_by_name('draw_empty').get_value() - self.same_style = menu.get_option_by_name('same_style').get_value() + self.circle = menu.get_option_by_name('circle').get_value() + self.background = menu.get_option_by_name('background').get_value() + self.radial = menu.get_option_by_name('radial').get_value() + pid = menu.get_option_by_name('pid').get_value() + self.draw_empty = menu.get_option_by_name('draw_empty').get_value() + self.same_style = menu.get_option_by_name('same_style').get_value() self.center_person = self.database.get_person_from_gramps_id(pid) if self.center_person is None: - raise ReportError(_("Person %s is not in the Database") % pid ) + raise ReportError(_("Person %s is not in the Database") % pid) self.graphic_style = [] self.text_style = [] - for i in range (0, self.max_generations): + for i in range(0, self.max_generations): self.graphic_style.append('FC-Graphic' + '%02d' % i) self.text_style.append('FC-Text' + '%02d' % i) @@ -204,7 +203,7 @@ class FanChart(Report): self.map = [None] * 2**self.max_generations self.text = {} - def apply_filter(self,person_handle,index): + def apply_filter(self, person_handle, index): """traverse the ancestors recursively until either the end of a line is found, or until we reach the maximum number of generations that we want to deal with""" @@ -218,151 +217,160 @@ class FanChart(Report): family_handle = person.get_main_parents_family_handle() if family_handle: family = self.database.get_family_from_handle(family_handle) - self.apply_filter(family.get_father_handle(),index*2) - self.apply_filter(family.get_mother_handle(),(index*2)+1) + self.apply_filter(family.get_father_handle(), index*2) + self.apply_filter(family.get_mother_handle(), (index*2)+1) def write_report(self): self.doc.start_page() - self.apply_filter(self.center_person.get_handle(),1) - n = self.center_person.get_primary_name().get_regular_name() + self.apply_filter(self.center_person.get_handle(), 1) + p_rn = self.center_person.get_primary_name().get_regular_name() if self.circle == FULL_CIRCLE: max_angle = 360.0 start_angle = 90 max_circular = 5 - x = self.doc.get_usable_width() / 2.0 - y = self.doc.get_usable_height() / 2.0 - min_xy = min (x, y) + _x_ = self.doc.get_usable_width() / 2.0 + _y_ = self.doc.get_usable_height() / 2.0 + min_xy = min(_x_, _y_) elif self.circle == HALF_CIRCLE: max_angle = 180.0 start_angle = 180 max_circular = 3 - x = (self.doc.get_usable_width()/2.0) - y = self.doc.get_usable_height() - min_xy = min (x, y) + _x_ = (self.doc.get_usable_width()/2.0) + _y_ = self.doc.get_usable_height() + min_xy = min(_x_, _y_) else: # quarter circle max_angle = 90.0 start_angle = 270 max_circular = 2 - x = 0 - y = self.doc.get_usable_height() - min_xy = min (self.doc.get_usable_width(), y) + _x_ = 0 + _y_ = self.doc.get_usable_height() + min_xy = min(self.doc.get_usable_width(), _y_) # choose one line or two lines translation according to the width title = self._("%(generations)d Generation Fan Chart " - "for %(person)s" ) % { - 'generations' : self.max_generations, - 'person' : n } + "for %(person)s") % { + 'generations' : self.max_generations, + 'person' : p_rn} title_nb_lines = 1 style_sheet = self.doc.get_style_sheet() if style_sheet: - paragraph_style = style_sheet.get_paragraph_style('FC-Title') - if paragraph_style: - font = paragraph_style.get_font() - if font: - title_width = pt2cm(self.doc.string_width(font, title)) - if title_width > self.doc.get_usable_width(): - title = self._("%(generations)d Generation Fan Chart " - "for\n%(person)s" ) % { - 'generations' : self.max_generations, - 'person' : n } - title_nb_lines = 2 + p_style = style_sheet.get_paragraph_style('FC-Title') + if p_style: + font = p_style.get_font() + if font: + title_width = utils.pt2cm(self.doc.string_width(font, + title)) + if title_width > self.doc.get_usable_width(): + title = self._( + "%(generations)d Generation Fan Chart " + "for\n%(person)s") % { + 'generations' : self.max_generations, + 'person' : p_rn} + title_nb_lines = 2 if self.circle == FULL_CIRCLE or self.circle == QUAR_CIRCLE: # adjust only if full circle or 1/4 circle in landscape mode if self.doc.get_usable_height() <= self.doc.get_usable_width(): # Should be in Landscape now style_sheet = self.doc.get_style_sheet() - paragraph_style = style_sheet.get_paragraph_style('FC-Title') - if paragraph_style: - font = paragraph_style.get_font() + p_style = style_sheet.get_paragraph_style('FC-Title') + if p_style: + font = p_style.get_font() if font: - fontsize = pt2cm(font.get_size()) - # y is vertical distance to center of circle, move center down 1 fontsize - y += fontsize*title_nb_lines - # min_XY is the diameter of the circle, subtract two fontsize + fontsize = utils.pt2cm(font.get_size()) + # _y_ is vertical distance to center of circle, + # move center down 1 fontsize + _y_ += fontsize*title_nb_lines + # min_XY is the diameter of the circle, + # subtract two fontsize # so we dont draw outside bottom of the paper - min_xy = min(min_xy, y - 2*fontsize*title_nb_lines) + min_xy = min(min_xy, _y_ - 2*fontsize*title_nb_lines) if self.max_generations > max_circular: block_size = min_xy / (self.max_generations * 2 - max_circular) else: block_size = min_xy / self.max_generations # adaptation of the fonts (title and others) - optimized_style_sheet = self.get_optimized_style_sheet(title, - max_circular, block_size, self.same_style, - not self.same_style, - # if same_style, use default generated colors - self.background == BACKGROUND_WHITE) + optimized_style_sheet = self.get_optimized_style_sheet( + title, max_circular, block_size, self.same_style, + not self.same_style, + # if same_style, use default generated colors + self.background == BACKGROUND_WHITE) if optimized_style_sheet: - self.doc.set_style_sheet(optimized_style_sheet) + self.doc.set_style_sheet(optimized_style_sheet) # title mark = IndexMark(title, INDEX_TYPE_TOC, 1) - self.doc.center_text ('FC-Graphic-title', title, - self.doc.get_usable_width() / 2, 0, mark) - #wheel - for generation in range (0, min (max_circular, self.max_generations)): - self.draw_circular (x, y, start_angle, max_angle, block_size, generation) - for generation in range (max_circular, self.max_generations): - self.draw_radial (x, y, start_angle, max_angle, block_size, generation) + self.doc.center_text('FC-Graphic-title', title, + self.doc.get_usable_width() / 2, 0, mark) + # wheel + for generation in range(0, min(max_circular, self.max_generations)): + self.draw_circular(_x_, _y_, + start_angle, max_angle, block_size, generation) + for generation in range(max_circular, self.max_generations): + self.draw_radial(_x_, _y_, + start_angle, max_angle, block_size, generation) self.doc.end_page() - def get_info(self,person_handle,generation): + def get_info(self, person_handle, generation): + """ get info about a person """ person = self.database.get_person_from_handle(person_handle) - pn = person.get_primary_name() + p_pn = person.get_primary_name() self.calendar = config.get('preferences.calendar-format-report') birth = get_birth_or_fallback(self.database, person) - b = "" + bth = "" if birth: - b = str(birth.get_date_object().to_calendar(self.calendar).get_year()) - if b == 0: - b = "" + bth = birth.get_date_object() + bth = str(bth.to_calendar(self.calendar).get_year()) + if bth == 0: + bth = "" elif birth.get_type() != EventType.BIRTH: - b += '*' + bth += '*' death = get_death_or_fallback(self.database, person) - d = "" + dth = "" if death: - d = str(death.get_date_object().to_calendar(self.calendar).get_year()) - if d == 0: - d = "" + dth = death.get_date_object() + dth = str(dth.to_calendar(self.calendar).get_year()) + if dth == 0: + dth = "" elif death.get_type() != EventType.DEATH: - d += '*' - if b and d: - val = "%s - %s" % (str(b),str(d)) - elif b: - val = "* %s" % (str(b)) - elif d: - val = "+ %s" % (str(d)) + dth += '*' + if bth and dth: + val = "%s - %s" % (str(bth), str(dth)) + elif bth: + val = "* %s" % (str(bth)) + elif dth: + val = "+ %s" % (str(dth)) else: val = "" if generation > 7: - if (pn.get_first_name() != "") and (pn.get_surname() != ""): - name = pn.get_first_name() + " " + pn.get_surname() + if (p_pn.get_first_name() != "") and (p_pn.get_surname() != ""): + name = p_pn.get_first_name() + " " + p_pn.get_surname() else: - name = pn.get_first_name() + pn.get_surname() + name = p_pn.get_first_name() + p_pn.get_surname() if (name != "") and (val != ""): string = name + ", " + val else: string = name + val - return [ string ] + return [string] elif generation == 7: - if (pn.get_first_name() != "") and (pn.get_surname() != ""): - name = pn.get_first_name() + " " + pn.get_surname() + if (p_pn.get_first_name() != "") and (p_pn.get_surname() != ""): + name = p_pn.get_first_name() + " " + p_pn.get_surname() else: - name = pn.get_first_name() + pn.get_surname() + name = p_pn.get_first_name() + p_pn.get_surname() if self.circle == FULL_CIRCLE: - return [ name, val ] + return [name, val] elif self.circle == HALF_CIRCLE: - return [ name, val ] + return [name, val] else: if (name != "") and (val != ""): string = name + ", " + val @@ -371,20 +379,21 @@ class FanChart(Report): return [string] elif generation == 6: if self.circle == FULL_CIRCLE: - return [ pn.get_first_name(), pn.get_surname(), val ] + return [p_pn.get_first_name(), p_pn.get_surname(), val] elif self.circle == HALF_CIRCLE: - return [ pn.get_first_name(), pn.get_surname(), val ] + return [p_pn.get_first_name(), p_pn.get_surname(), val] else: - if (pn.get_first_name() != "") and (pn.get_surname() != ""): - name = pn.get_first_name() + " " + pn.get_surname() + if (p_pn.get_first_name() != "") and (p_pn.get_surname() != ""): + name = p_pn.get_first_name() + " " + p_pn.get_surname() else: - name = pn.get_first_name() + pn.get_surname() - return [ name, val ] + name = p_pn.get_first_name() + p_pn.get_surname() + return [name, val] else: - return [ pn.get_first_name(), pn.get_surname(), val ] + return [p_pn.get_first_name(), p_pn.get_surname(), val] def get_max_width_for_circles(self, rad1, rad2, max_centering_proportion): - """ + r""" + (the "r" in the above line is to keep pylint happy) __ /__\ <- compute the line width which is drawable between 2 circles. / _ \ max_centering_proportion : 0, touching the circle1, 1, @@ -400,13 +409,14 @@ class FanChart(Report): return sin(acos(rmid/rad2)) * rad2 * 2 def get_max_width_for_circles_line(self, rad1, rad2, line, nb_lines, - centering = False): - """ + centering=False): + r""" + (the "r" in the above line is to keep pylint happy) __ /__\ <- compute the line width which is drawable between 2 circles. - / _ \ instead of a max_centering_proportion, you get a line/nb_lines position. - | |_| | (we suppose that lines have the same heights) - | | for example, if you've 2 lines to draw, + / _ \ instead of a max_centering_proportion, you get a + | |_| | line/nb_lines position. (we suppose that lines have the + | | same heights.) for example, if you've 2 lines to draw, \ / line 2 max width is at the 2/3 between the 2 circles \__/ """ @@ -417,7 +427,7 @@ class FanChart(Report): line/float(nb_lines+1)) def get_optimized_font_size_for_text(self, rad1, rad2, text, font, - centering = False): + centering=False): """ a text can be several lines find the font size equals or lower than font.get_size() which fit @@ -429,7 +439,8 @@ class FanChart(Report): i = 1 nb_lines = len(text) for line in text: - font_size = self.get_optimized_font_size(line, font, + font_size = self.get_optimized_font_size( + line, font, self.get_max_width_for_circles_line(rad1, rad2, i, nb_lines, centering)) i += 1 @@ -443,10 +454,10 @@ class FanChart(Report): or smaller than font which make line fit into max_width """ test_font = FontStyle(font) - w = pt2cm(self.doc.string_width(test_font, line)) - while w > max_width and test_font.get_size() > 1: + width = utils.pt2cm(self.doc.string_width(test_font, line)) + while width > max_width and test_font.get_size() > 1: test_font.set_size(test_font.get_size() -1) - w = pt2cm(self.doc.string_width(test_font, line)) + width = utils.pt2cm(self.doc.string_width(test_font, line)) return test_font.get_size() def get_optimized_style_sheet(self, title, max_circular, block_size, @@ -457,66 +468,69 @@ class FanChart(Report): returns an optimized (modified) style sheet which make fanchart look nicer """ - redefined_style_sheet = self.doc.get_style_sheet() - if not redefined_style_sheet: + new_style_sheet = self.doc.get_style_sheet() + if not new_style_sheet: return self.doc.get_style_sheet() # update title font size pstyle_name = 'FC-Title' - paragraph_style = redefined_style_sheet.get_paragraph_style(pstyle_name) - if paragraph_style: - title_font = paragraph_style.get_font() + p_style = new_style_sheet.get_paragraph_style(pstyle_name) + if p_style: + title_font = p_style.get_font() if title_font: - title_width = pt2cm(self.doc.string_multiline_width(title_font, - title)) + title_width = utils.pt2cm( + self.doc.string_multiline_width(title_font, title)) while (title_width > self.doc.get_usable_width() and title_font.get_size() > 1): title_font.set_size(title_font.get_size()-1) - title_width = pt2cm(self.doc.string_multiline_width( - title_font, title)) - redefined_style_sheet.add_paragraph_style(pstyle_name, - paragraph_style) + title_width = utils.pt2cm( + self.doc.string_multiline_width(title_font, title)) + new_style_sheet.add_paragraph_style(pstyle_name, p_style) # biggest font allowed is the one of the fist generation, after, # always lower than the previous one - paragraph_style = redefined_style_sheet.get_paragraph_style(self.text_style[0]) + p_style = new_style_sheet.get_paragraph_style(self.text_style[0]) font = None - if paragraph_style: - font = paragraph_style.get_font() + if p_style: + font = p_style.get_font() if font: previous_generation_font_size = font.get_size() - for generation in range (0, self.max_generations): + for generation in range(0, self.max_generations): gstyle_name = self.graphic_style[generation] - pstyle_name = self.text_style [generation] - g = redefined_style_sheet.get_draw_style(gstyle_name) + pstyle_name = self.text_style[generation] + g_style = new_style_sheet.get_draw_style(gstyle_name) - # paragraph_style is a copy of 'FC-Text' - use different style + # p_style is a copy of 'FC-Text' - use different style # to be able to auto change some fonts for some generations if map_style_from_single: - paragraph_style = redefined_style_sheet.get_paragraph_style('FC-Text') + p_style = new_style_sheet.get_paragraph_style('FC-Text') else: - paragraph_style = redefined_style_sheet.get_paragraph_style(pstyle_name) + p_style = new_style_sheet.get_paragraph_style(pstyle_name) - if g and paragraph_style: - # set graphic colors to paragraph colors, while it's fonctionnaly + if g_style and p_style: + # set graphic colors to paragraph colors, + # while it's functionnaly # the same for fanchart or make backgrounds white if make_background_white: - g.set_fill_color((255,255,255)) - redefined_style_sheet.add_draw_style(gstyle_name, g) + g_style.set_fill_color((255, 255, 255)) + new_style_sheet.add_draw_style(gstyle_name, g_style) elif map_paragraphs_colors_to_graphics: - pstyle = redefined_style_sheet.get_paragraph_style(pstyle_name) + pstyle = new_style_sheet.get_paragraph_style( + pstyle_name) if pstyle: - g.set_fill_color(pstyle.get_background_color()) - redefined_style_sheet.add_draw_style(gstyle_name, g) + g_style.set_fill_color( + pstyle.get_background_color()) + new_style_sheet.add_draw_style(gstyle_name, + g_style) # adapt font size if too big segments = 2**generation - if generation < min (max_circular, self.max_generations): + if generation < min(max_circular, self.max_generations): # adpatation for circular fonts - rad1, rad2 = self.get_circular_radius(block_size, - generation, self.circle) - font = paragraph_style.get_font() + rad1, rad2 = self.get_circular_radius( + block_size, generation, self.circle) + font = p_style.get_font() if font: min_font_size = font.get_size() # find the smallest font required @@ -524,55 +538,57 @@ class FanChart(Report): if self.map[index]: font_size = \ self.get_optimized_font_size_for_text( - rad1, rad2, self.text[index], - paragraph_style.get_font(), - (self.circle == FULL_CIRCLE and - generation == 0) - ) + rad1, rad2, self.text[index], + p_style.get_font(), + (self.circle == FULL_CIRCLE and + generation == 0) + ) if font_size < min_font_size: min_font_size = font_size font.set_size(min(previous_generation_font_size, - min_font_size)) + min_font_size)) else: # adaptation for radial fonts # find the largest string for the generation - longest_line = "" + longest_line = "" longest_width = 0 for index in range(segments - 1, 2*segments - 1): if self.map[index]: for line in self.text[index]: - width = pt2cm(self.doc.string_multiline_width( - paragraph_style.get_font(), line)) + width = utils.pt2cm( + self.doc.string_multiline_width( + p_style.get_font(), line)) if width > longest_width: - longest_line = line + longest_line = line longest_width = width # determine maximum width allowed for this generation - rad1, rad2 = self.get_radial_radius(block_size, - generation, self.circle) + rad1, rad2 = self.get_radial_radius( + block_size, generation, self.circle) max_width = rad2 - rad1 - # reduce the font so that longest_width fit into max_width - font = paragraph_style.get_font() + # reduce the font so that longest_width + # fit into max_width + font = p_style.get_font() if font: font.set_size(min(previous_generation_font_size, - self.get_optimized_font_size(longest_line, - paragraph_style.get_font(), - max_width)) - ) + self.get_optimized_font_size( + longest_line, + p_style.get_font(), + max_width))) # redefine the style - redefined_style_sheet.add_paragraph_style(pstyle_name, - paragraph_style) - font = paragraph_style.get_font() + new_style_sheet.add_paragraph_style(pstyle_name, p_style) + font = p_style.get_font() if font: previous_generation_font_size = font.get_size() # finished - return redefined_style_sheet + return new_style_sheet - def draw_circular(self, x, y, start_angle, max_angle, size, generation): + def draw_circular(self, _x_, _y_, + start_angle, max_angle, size, generation): segments = 2**generation delta = max_angle / segments end_angle = start_angle @@ -583,19 +599,20 @@ class FanChart(Report): for index in range(segments - 1, 2*segments - 1): start_angle = end_angle end_angle = start_angle + delta - (xc,yc) = draw_wedge(self.doc, graphic_style, x, y, rad2, - start_angle, end_angle, - self.map[index] or self.draw_empty, rad1) + (_xc, _yc) = draw_wedge(self.doc, graphic_style, _x_, _y_, rad2, + start_angle, end_angle, + self.map[index] or self.draw_empty, rad1) if self.map[index]: if (generation == 0) and self.circle == FULL_CIRCLE: - yc = y + _yc = _y_ person = self.database.get_person_from_handle(self.map[index]) mark = utils.get_person_mark(self.database, person) self.doc.rotate_text(graphic_style, self.text[index], - xc, yc, text_angle, mark) + _xc, _yc, text_angle, mark) text_angle += delta def get_radial_radius(self, size, generation, circle): + """ determine the radius """ if circle == FULL_CIRCLE: rad1 = size * ((generation * 2) - 5) rad2 = size * ((generation * 2) - 3) @@ -608,9 +625,11 @@ class FanChart(Report): return rad1, rad2 def get_circular_radius(self, size, generation, circle): + """ determine the radius """ return size * generation, size * (generation + 1) - def draw_radial(self, x, y, start_angle, max_angle, size, generation): + def draw_radial(self, _x_, _y_, + start_angle, max_angle, size, generation): segments = 2**generation delta = max_angle / segments end_angle = start_angle @@ -621,19 +640,21 @@ class FanChart(Report): for index in range(segments - 1, 2*segments - 1): start_angle = end_angle end_angle = start_angle + delta - (xc,yc) = draw_wedge(self.doc, graphic_style, x, y, rad2, - start_angle, end_angle, - self.map[index] or self.draw_empty, rad1) + (_xc, _yc) = draw_wedge(self.doc, graphic_style, _x_, _y_, rad2, + start_angle, end_angle, + self.map[index] or self.draw_empty, rad1) text_angle += delta if self.map[index]: person = self.database.get_person_from_handle(self.map[index]) mark = utils.get_person_mark(self.database, person) - if self.radial == RADIAL_UPRIGHT and (start_angle >= 90) and (start_angle < 270): + if (self.radial == RADIAL_UPRIGHT + and (start_angle >= 90) + and (start_angle < 270)): self.doc.rotate_text(graphic_style, self.text[index], - xc, yc, text_angle + 180, mark) + _xc, _yc, text_angle + 180, mark) else: self.doc.rotate_text(graphic_style, self.text[index], - xc, yc, text_angle, mark) + _xc, _yc, text_angle, mark) #------------------------------------------------------------------------ # @@ -641,9 +662,10 @@ class FanChart(Report): # #------------------------------------------------------------------------ class FanChartOptions(MenuReportOptions): + """ options for fanchart report """ def __init__(self, name, dbase): - self.MAX_GENERATIONS = 11 + self.max_generations = 11 MenuReportOptions.__init__(self, name, dbase) @@ -661,7 +683,7 @@ class FanChartOptions(MenuReportOptions): stdoptions.add_living_people_option(menu, category_name) - max_gen = NumberOption(_("Generations"), 5, 1, self.MAX_GENERATIONS) + max_gen = NumberOption(_("Generations"), 5, 1, self.max_generations) max_gen.set_help(_("The number of generations " "to include in the report")) menu.add_option(category_name, "maxgen", max_gen) @@ -670,8 +692,8 @@ class FanChartOptions(MenuReportOptions): circle.add_item(FULL_CIRCLE, _('full circle')) circle.add_item(HALF_CIRCLE, _('half circle')) circle.add_item(QUAR_CIRCLE, _('quarter circle')) - circle.set_help( _("The form of the graph: full circle, half circle," - " or quarter circle.")) + circle.set_help(_("The form of the graph: full circle, half circle," + " or quarter circle.")) menu.add_option(category_name, "circle", circle) background = EnumeratedListOption(_('Background color'), BACKGROUND_GEN) @@ -681,8 +703,8 @@ class FanChartOptions(MenuReportOptions): " dependent")) menu.add_option(category_name, "background", background) - radial = EnumeratedListOption( _('Orientation of radial texts'), - RADIAL_UPRIGHT ) + radial = EnumeratedListOption(_('Orientation of radial texts'), + RADIAL_UPRIGHT) radial.add_item(RADIAL_UPRIGHT, _('upright')) radial.add_item(RADIAL_ROUNDABOUT, _('roundabout')) radial.set_help(_("Print radial texts upright or roundabout")) @@ -700,59 +722,60 @@ class FanChartOptions(MenuReportOptions): stdoptions.add_localization_option(menu, category_name) - def make_default_style(self,default_style): + def make_default_style(self, default_style): """Make the default output style for the Fan Chart report.""" - BACKGROUND_COLORS = [ - (255, 63, 0), - (255,175, 15), - (255,223, 87), - (255,255,111), - (159,255,159), - (111,215,255), - ( 79,151,255), - (231, 23,255), - (231, 23,221), - (210,170,124), - (189,153,112) + background_colors = [(255, 63, 0), + (255, 175, 15), + (255, 223, 87), + (255, 255, 111), + (159, 255, 159), + (111, 215, 255), + (79, 151, 255), + (231, 23, 255), + (231, 23, 221), + (210, 170, 124), + (189, 153, 112) ] #Paragraph Styles - f = FontStyle() - f.set_size(18) - f.set_bold(1) - f.set_type_face(FONT_SANS_SERIF) - p = ParagraphStyle() - p.set_font(f) - p.set_alignment(PARA_ALIGN_CENTER) - p.set_description(_('The style used for the title.')) - default_style.add_paragraph_style("FC-Title",p) + f_style = FontStyle() + f_style.set_size(18) + f_style.set_bold(1) + f_style.set_type_face(FONT_SANS_SERIF) + p_style = ParagraphStyle() + p_style.set_font(f_style) + p_style.set_alignment(PARA_ALIGN_CENTER) + p_style.set_description(_('The style used for the title.')) + default_style.add_paragraph_style("FC-Title", p_style) - f = FontStyle() - f.set_size(9) - f.set_type_face(FONT_SANS_SERIF) - p = ParagraphStyle() - p.set_font(f) - p.set_alignment(PARA_ALIGN_CENTER) - p.set_description(_('The basic style used for the default text display.')) - default_style.add_paragraph_style("FC-Text", p) + f_style = FontStyle() + f_style.set_size(9) + f_style.set_type_face(FONT_SANS_SERIF) + p_style = ParagraphStyle() + p_style.set_font(f_style) + p_style.set_alignment(PARA_ALIGN_CENTER) + p_style.set_description( + _('The basic style used for the default text display.')) + default_style.add_paragraph_style("FC-Text", p_style) - for i in range (0, self.MAX_GENERATIONS): - f = FontStyle() - f.set_size(9) - f.set_type_face(FONT_SANS_SERIF) - p = ParagraphStyle() - p.set_font(f) - p.set_alignment(PARA_ALIGN_CENTER) - p.set_description(_('The style used for the text display of generation "%d"') % i) - default_style.add_paragraph_style("FC-Text" + "%02d" % i, p) + for i in range(0, self.max_generations): + f_style = FontStyle() + f_style.set_size(9) + f_style.set_type_face(FONT_SANS_SERIF) + p_style = ParagraphStyle() + p_style.set_font(f_style) + p_style.set_alignment(PARA_ALIGN_CENTER) + p_style.set_description( + _('The style used for the text display of generation "%d"') % i) + default_style.add_paragraph_style("FC-Text" + "%02d" % i, p_style) # GraphicsStyles - g = GraphicsStyle() - g.set_paragraph_style('FC-Title') - default_style.add_draw_style('FC-Graphic-title', g) + g_style = GraphicsStyle() + g_style.set_paragraph_style('FC-Title') + default_style.add_draw_style('FC-Graphic-title', g_style) - for i in range (0, self.MAX_GENERATIONS): - g = GraphicsStyle() - g.set_paragraph_style('FC-Text' + '%02d' % i) - g.set_fill_color(BACKGROUND_COLORS[i]) - default_style.add_draw_style('FC-Graphic' + '%02d' % i, g) + for i in range(0, self.max_generations): + g_style = GraphicsStyle() + g_style.set_paragraph_style('FC-Text' + '%02d' % i) + g_style.set_fill_color(background_colors[i]) + default_style.add_draw_style('FC-Graphic' + '%02d' % i, g_style) From 0820e70499b84ef0bf4911586e80523044c7ef22 Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Wed, 25 May 2016 15:42:04 -0400 Subject: [PATCH 07/11] Additional fixes for narrativeweb --- gramps/plugins/webreport/narrativeweb.py | 328 +++++++++++------------ 1 file changed, 156 insertions(+), 172 deletions(-) diff --git a/gramps/plugins/webreport/narrativeweb.py b/gramps/plugins/webreport/narrativeweb.py index 0388961d8..cfafd0c8c 100644 --- a/gramps/plugins/webreport/narrativeweb.py +++ b/gramps/plugins/webreport/narrativeweb.py @@ -125,7 +125,7 @@ from gramps.gen.utils.image import image_size # , resize_to_jpeg_buffer from gramps.gen.display.name import displayer as _nd from gramps.gen.display.place import displayer as _pd from gramps.gen.datehandler import displayer as _dd -from gramps.gen.proxy import LivingProxyDb, CacheProxyDb +from gramps.gen.proxy import CacheProxyDb from gramps.plugins.lib.libhtmlconst import _CHARACTER_SETS, _CC, _COPY_OPTIONS from gramps.gen.datehandler import get_date @@ -418,7 +418,6 @@ _KEYPERSON, _KEYPLACE, _KEYEVENT, _ALPHAEVENT = 0, 1, 2, 3 # Web page filename extensions _WEB_EXT = ['.html', '.htm', '.shtml', '.php', '.php3', '.cgi'] -_INCLUDE_LIVING_VALUE = LivingProxyDb.MODE_INCLUDE_ALL _NAME_COL = 3 _DEFAULT_MAX_IMG_WIDTH = 800 # resize images that are wider than this @@ -536,37 +535,6 @@ def format_date(date): return val return "" -def sort_on_name_and_grampsid(obj, dbase): - """ Used to sort on name and gramps ID. """ - - person = dbase.get_person_from_handle(obj) - name = _nd.display(person) - return (name, person.get_gramps_id()) - -def copy_thumbnail(report, handle, photo, region=None): - """ - Given a handle (and optional region) make (if needed) an - up-to-date cache of a thumbnail, and call report.copy_file - to copy the cached thumbnail to the website. - Return the new path to the image. - """ - to_dir = report.build_path('thumb', handle) - to_path = os.path.join(to_dir, handle) + ( - ('%d,%d-%d,%d.png' % region) if region else '.png' - ) - - if photo.get_mime_type(): - full_path = media_path_full(report.database, photo.get_path()) - from_path = get_thumbnail_path(full_path, - photo.get_mime_type(), - region) - if not os.path.isfile(from_path): - from_path = CSS["Document"]["filename"] - else: - from_path = CSS["Document"]["filename"] - report.copy_file(from_path, to_path) - return to_path - # pylint: disable=unused-variable # pylint: disable=unused-argument @@ -591,7 +559,6 @@ class BasePage: self.title_str = title self.gid = gid self.bibli = Bibliography() - self.dbase_ = report.database self.page_title = "" @@ -630,6 +597,44 @@ class BasePage: """ pass + def sort_on_name_and_grampsid(self, handle): + """ Used to sort on name and gramps ID. """ + person = self.report.database.get_person_from_handle(handle) + name = _nd.display(person) + return (name, person.get_gramps_id()) + + def sort_on_grampsid(self, event_ref): + """ + Sort on gramps ID + """ + evt = self.report.database.get_event_from_handle( + event_ref.ref) + return evt.get_gramps_id() + + def copy_thumbnail(self, handle, photo, region=None): + """ + Given a handle (and optional region) make (if needed) an + up-to-date cache of a thumbnail, and call report.copy_file + to copy the cached thumbnail to the website. + Return the new path to the image. + """ + to_dir = self.report.build_path('thumb', handle) + to_path = os.path.join(to_dir, handle) + ( + ('%d,%d-%d,%d.png' % region) if region else '.png' + ) + + if photo.get_mime_type(): + full_path = media_path_full(self.report.database, photo.get_path()) + from_path = get_thumbnail_path(full_path, + photo.get_mime_type(), + region) + if not os.path.isfile(from_path): + from_path = CSS["Document"]["filename"] + else: + from_path = CSS["Document"]["filename"] + self.report.copy_file(from_path, to_path) + return to_path + def get_nav_menu_hyperlink(self, url_fname, nav_text): """ Returns the navigation menu hyperlink @@ -699,7 +704,7 @@ class BasePage: section += table for family_handle in family_list: - family = self.dbase_.get_family_from_handle(family_handle) + family = self.report.database.get_family_from_handle(family_handle) if family: link = self.family_link( family_handle, @@ -719,7 +724,7 @@ class BasePage: spouse_handle = ReportUtils.find_spouse(individual, family) if spouse_handle: - spouse = self.dbase_.get_person_from_handle( + spouse = self.report.database.get_person_from_handle( spouse_handle) if spouse: table += self.display_spouse(spouse, family, @@ -749,7 +754,7 @@ class BasePage: family.get_mother_handle()]: person = None if person_handle: - person = self.dbase_.get_person_from_handle( + person = self.report.database.get_person_from_handle( person_handle) if person: table += self.display_spouse(person, @@ -783,7 +788,7 @@ class BasePage: if not self.inc_families: notelist = family.get_note_list() for notehandle in notelist: - note = self.dbase_.get_note_from_handle(notehandle) + note = self.report.database.get_note_from_handle(notehandle) if note: trow = Html("tr") + ( Html("td", " ", class_="ColumnType", inline=True), @@ -812,11 +817,11 @@ class BasePage: # add individual's children event places to family map... if self.familymappages: for handle in childlist: - child = self.dbase_.get_person_from_handle(handle) + child = self.report.database.get_person_from_handle(handle) if child: self._get_event_place(child, place_lat_long) - children = add_birthdate(self.dbase_, childlist) + children = add_birthdate(self.report.database, childlist) if birthorder: children = sorted(children) @@ -875,7 +880,7 @@ class BasePage: # family event else: - _obj = self.dbase_.get_family_from_handle(handle) + _obj = self.report.database.get_family_from_handle(handle) if _obj: # husband and spouse in this example, @@ -1064,7 +1069,7 @@ class BasePage: place_handle = event.get_place_handle() if place_handle: - place = self.dbase_.get_place_from_handle(place_handle) + place = self.report.database.get_place_from_handle(place_handle) if place: self.append_to_place_lat_long(place, event, place_lat_long) @@ -1138,7 +1143,7 @@ class BasePage: # 3 = place handle, 4 = event date, 5 = event type found = any(data[3] == place_handle for data in place_lat_long) if not found: - placetitle = _pd.display(self.dbase_, place) + placetitle = _pd.display(self.report.database, place) latitude = place.get_latitude() longitude = place.get_longitude() if latitude and longitude: @@ -1173,11 +1178,11 @@ class BasePage: evt_ref_list = person.get_event_ref_list() if evt_ref_list: for evt_ref in evt_ref_list: - event = self.dbase_.get_event_from_handle(evt_ref.ref) + event = self.report.database.get_event_from_handle(evt_ref.ref) if event: place_handle = event.get_place_handle() if place_handle: - place = self.dbase_.get_place_from_handle( + place = self.report.database.get_place_from_handle( place_handle) if place: self.append_to_place_lat_long(place, event, @@ -1222,13 +1227,13 @@ class BasePage: husband_handle = family.get_father_handle() if husband_handle: - husband = self.dbase_.get_person_from_handle(husband_handle) + husband = self.report.database.get_person_from_handle(husband_handle) else: husband = None spouse_handle = family.get_mother_handle() if spouse_handle: - spouse = self.dbase_.get_person_from_handle(spouse_handle) + spouse = self.report.database.get_person_from_handle(spouse_handle) else: spouse = None @@ -1291,7 +1296,7 @@ class BasePage: table += tbody for evt_ref in event_ref_list: - event = self.dbase_.get_event_from_handle(evt_ref.ref) + event = self.report.database.get_event_from_handle(evt_ref.ref) # add event body row tbody += self.display_event_row(event, evt_ref, place_lat_long, @@ -1312,11 +1317,11 @@ class BasePage: place = None place_handle = evt.get_place_handle() if place_handle: - place = self.dbase_.get_place_from_handle(place_handle) + place = self.report.database.get_place_from_handle(place_handle) place_hyper = None if place: - place_name = _pd.display(self.dbase_, place, evt.get_date_object()) + place_name = _pd.display(self.report.database, place, evt.get_date_object()) place_hyper = self.place_link(place_handle, place_name, uplink=uplink) @@ -1372,9 +1377,9 @@ class BasePage: place_hyper = " " place_handle = ordobj.get_place_handle() if place_handle: - place = self.dbase_.get_place_from_handle(place_handle) + place = self.report.database.get_place_from_handle(place_handle) if place: - place_title = _pd.display(self.dbase_, place) + place_title = _pd.display(self.report.database, place) place_hyper = self.place_link(place_handle, place_title, place.get_gramps_id(), uplink=True) @@ -2145,7 +2150,7 @@ class BasePage: # get all of the backlinks to this media object; meaning all of # the people, events, places, etc..., that use this image _region_items = set() - for (classname, newhandle) in self.dbase_.find_backlink_handles(handle, + for (classname, newhandle) in self.report.database.find_backlink_handles(handle, include_classes=["Person", "Family", "Event", "Place"]): # for each of the backlinks, get the relevant object from the db @@ -2158,7 +2163,7 @@ class BasePage: # Is this a person for whom we have built a page: if self.report.person_in_webreport(newhandle): # If so, let's add a link to them: - _obj = self.dbase_.get_person_from_handle(newhandle) + _obj = self.report.database.get_person_from_handle(newhandle) if _obj: # What is the shortest possible name we could use # for this person? @@ -2169,16 +2174,16 @@ class BasePage: _linkurl = self.report.build_url_fname_html(_obj.handle, "ppl", True) elif classname == "Family": - _obj = self.dbase_.get_family_from_handle(newhandle) + _obj = self.report.database.get_family_from_handle(newhandle) partner1_handle = _obj.get_father_handle() partner2_handle = _obj.get_mother_handle() partner1 = None partner2 = None if partner1_handle: - partner1 = self.dbase_.get_person_from_handle( + partner1 = self.report.database.get_person_from_handle( partner1_handle) if partner2_handle: - partner2 = self.dbase_.get_person_from_handle( + partner2 = self.report.database.get_person_from_handle( partner2_handle) if partner2 and partner1: _name = partner1.get_primary_name().get_first_name() @@ -2195,15 +2200,15 @@ class BasePage: if not _name: _name = _UNKNOWN elif classname == "Event": - _obj = self.dbase_.get_event_from_handle(newhandle) + _obj = self.report.database.get_event_from_handle(newhandle) _name = _obj.get_description() if not _name: _name = _UNKNOWN _linkurl = self.report.build_url_fname_html(_obj.handle, "evt", True) elif classname == "Place": - _obj = self.dbase_.get_place_from_handle(newhandle) - _name = _pd.display(self.dbase_, _obj) + _obj = self.report.database.get_place_from_handle(newhandle) + _name = _pd.display(self.report.database, _obj) if not _name: _name = _UNKNOWN _linkurl = self.report.build_url_fname_html(newhandle, @@ -2290,8 +2295,7 @@ class BasePage: if region: # make a thumbnail of this region - newpath = copy_thumbnail(self.report, photo_handle, - photo, region) + newpath = self.copy_thumbnail(photo_handle, photo, region) newpath = self.report.build_url_fname(newpath, uplink=True) snapshot += self.media_link(photo_handle, newpath, descr, @@ -2578,7 +2582,7 @@ class BasePage: for citation in citationlist: cindex += 1 # Add this source and its references to the page - source = self.dbase_.get_source_from_handle( + source = self.report.database.get_source_from_handle( citation.get_source_handle()) if source is not None: if source.get_author(): @@ -2611,7 +2615,7 @@ class BasePage: if self.create_media: for media_ref in sref.get_media_list(): media_handle = media_ref.get_reference_handle() - media = self.dbase_.get_media_from_handle( + media = self.report.database.get_media_from_handle( media_handle) if media: mime_type = media.get_mime_type() @@ -2646,7 +2650,7 @@ class BasePage: usedescr=False), inline=True) for handle in sref.get_note_list(): - this_note = self.dbase_.get_note_from_handle(handle) + this_note = self.report.database.get_note_from_handle(handle) if this_note is not None: tmp += Html("li", "%s: %s" % ( @@ -2788,7 +2792,7 @@ class BasePage: # The person is not included in the webreport link = "" if person is None: - person = self.dbase_.get_person_from_handle(person_handle) + person = self.report.database.get_person_from_handle(person_handle) if person: name = self.report.get_person_name(person) gid = person.get_gramps_id() @@ -2938,7 +2942,7 @@ class BasePage: ) tbody += trow - mlocation = get_main_location(self.dbase_, place) + mlocation = get_main_location(self.report.database, place) for (label, data) in [ (STREET, mlocation.get(PlaceType.STREET, '')), (LOCALITY, mlocation.get(PlaceType.LOCALITY, '')), @@ -2987,7 +2991,7 @@ class BasePage: for placeref in place.get_placeref_list(): place_date = get_date(placeref) if place_date != "": - parent_place = self.dbase_.get_place_from_handle(placeref.ref) + parent_place = self.report.database.get_place_from_handle(placeref.ref) parent_name = parent_place.get_name().get_value() trow = Html('tr') + ( Html("td", LOCATIONS, class_="ColumnAttribute", @@ -3054,7 +3058,7 @@ class BasePage: index = 1 for repo_ref in repo_ref_list: - repository = self.dbase_.get_repository_from_handle( + repository = self.report.database.get_repository_from_handle( repo_ref.ref) if repository: @@ -3278,9 +3282,9 @@ class SurnamePage(BasePage): table += tbody for person_handle in sorted(ppl_handle_list, - key=lambda x: sort_on_name_and_grampsid(x, self.dbase_)): + key=self.sort_on_name_and_grampsid): - person = self.dbase_.get_person_from_handle(person_handle) + person = self.report.database.get_person_from_handle(person_handle) if person.get_change_time() > ldatec: ldatec = person.get_change_time() trow = Html("tr") @@ -3297,7 +3301,7 @@ class SurnamePage(BasePage): tcell = Html("td", class_="ColumnBirth", inline=True) trow += tcell - birth_date = _find_birth_date(self.dbase_, person) + birth_date = _find_birth_date(self.report.database, person) if birth_date is not None: if birth_date.fallback: tcell += Html('em', _dd.display(birth_date), @@ -3312,7 +3316,7 @@ class SurnamePage(BasePage): tcell = Html("td", class_="ColumnDeath", inline=True) trow += tcell - death_date = _find_death_date(self.dbase_, person) + death_date = _find_death_date(self.report.database, person) if death_date is not None: if death_date.fallback: tcell += Html('em', _dd.display(death_date), @@ -3330,7 +3334,7 @@ class SurnamePage(BasePage): first_family = True if family_list: for family_handle in family_list: - family = self.dbase_.get_family_from_handle( + family = self.report.database.get_family_from_handle( family_handle) partner_handle = ReportUtils.find_spouse(person, family) @@ -3349,18 +3353,18 @@ class SurnamePage(BasePage): parent_handle_list = person.get_parent_family_handle_list() if parent_handle_list: parent_handle = parent_handle_list[0] - family = self.dbase_.get_family_from_handle( + family = self.report.database.get_family_from_handle( parent_handle) father_id = family.get_father_handle() mother_id = family.get_mother_handle() mother = father = None if father_id: - father = self.dbase_.get_person_from_handle( + father = self.report.database.get_person_from_handle( father_id) if father: father_name = self.get_name(father) if mother_id: - mother = self.dbase_.get_person_from_handle( + mother = self.report.database.get_person_from_handle( mother_id) if mother: mother_name = self.get_name(mother) @@ -3474,7 +3478,7 @@ class FamilyPages(BasePage): # because they are not in the original family list. pers_fam_dict = defaultdict(list) for family_handle in fam_list: - family = self.dbase_.get_family_from_handle(family_handle) + family = self.report.database.get_family_from_handle(family_handle) if family: if family.get_change_time() > ldatec: ldatec = family.get_change_time() @@ -3486,7 +3490,7 @@ class FamilyPages(BasePage): pers_fam_dict[spouse_handle].append(family) # add alphabet navigation - index_list = get_first_letters(self.dbase_, pers_fam_dict.keys(), + index_list = get_first_letters(self.report.database, pers_fam_dict.keys(), _KEYPERSON) alpha_nav = alphabet_navigation(index_list) if alpha_nav: @@ -3518,7 +3522,7 @@ class FamilyPages(BasePage): table += tbody # begin displaying index list - ppl_handle_list = sort_people(self.dbase_, pers_fam_dict.keys()) + ppl_handle_list = sort_people(self.report.database, pers_fam_dict.keys()) first = True for (surname, handle_list) in ppl_handle_list: @@ -3530,9 +3534,8 @@ class FamilyPages(BasePage): # get person from sorted database list for person_handle in sorted(handle_list, - key=lambda x: sort_on_name_and_grampsid(x, - self.dbase_)): - person = self.dbase_.get_person_from_handle( + key=self.sort_on_name_and_grampsid): + person = self.report.database.get_person_from_handle( person_handle) if person: family_list = sorted(pers_fam_dict[person_handle], @@ -3589,19 +3592,11 @@ class FamilyPages(BasePage): trow += (tcell1, tcell2) if fam_evt_ref_list: - def sort_on_grampsid(obj): - """ - Sort on gramps ID - """ - evt = self.dbase_.get_event_from_handle( - obj.ref) - return evt.get_gramps_id() - fam_evt_srt_ref_list = sorted( - fam_evt_ref_list, - key=lambda x: sort_on_grampsid(x)) + fam_evt_ref_list, + key=self.sort_on_grampsid) for evt_ref in fam_evt_srt_ref_list: - evt = self.dbase_.get_event_from_handle( + evt = self.report.database.get_event_from_handle( evt_ref.ref) if evt: evt_type = evt.get_type() @@ -3672,7 +3667,7 @@ class FamilyPages(BasePage): # the family event media here if not self.inc_events: for evt_ref in family.get_event_ref_list(): - event = self.dbase_.get_event_from_handle(evt_ref.ref) + event = self.report.database.get_event_from_handle(evt_ref.ref) media_list += event.get_media_list() thumbnail = self.disp_first_img_as_thumbnail(media_list, family) @@ -3806,7 +3801,7 @@ class PlacePages(BasePage): placelist += Html("p", msg, id="description") # begin alphabet navigation - index_list = get_first_letters(self.dbase_, place_handles, + index_list = get_first_letters(self.report.database, place_handles, _KEYPLACE) alpha_nav = alphabet_navigation(index_list) if alpha_nav is not None: @@ -3837,7 +3832,7 @@ class PlacePages(BasePage): handle_list = sorted(place_handles, key=lambda x: - SORT_KEY(ReportUtils.place_name(self.dbase_, x))) + SORT_KEY(ReportUtils.place_name(self.report.database, x))) first = True # begin table body @@ -3845,13 +3840,13 @@ class PlacePages(BasePage): table += tbody for place_handle in handle_list: - place = self.dbase_.get_place_from_handle(place_handle) + place = self.report.database.get_place_from_handle(place_handle) if place: if place.get_change_time() > ldatec: ldatec = place.get_change_time() - place_title = ReportUtils.place_name(self.dbase_, + place_title = ReportUtils.place_name(self.report.database, place_handle) - main_location = get_main_location(self.dbase_, place) + main_location = get_main_location(self.report.database, place) if place_title and not place_title.isspace(): letter = get_index_letter(first_letter(place_title), @@ -3934,7 +3929,7 @@ class PlacePages(BasePage): output_file, sio = self.report.create_file(place_handle, "plc") self.uplink = True - self.page_title = _pd.display(self.dbase_, place) + self.page_title = _pd.display(self.report.database, place) placepage, head, body = self.write_header(_("Places")) self.placemappages = self.report.options['placemappages'] @@ -4136,7 +4131,7 @@ class EventPages(BasePage): eventlist += Html("p", msg, id="description") # get alphabet navigation... - index_list = get_first_letters(self.dbase_, event_types, + index_list = get_first_letters(self.report.database, event_types, _ALPHAEVENT) alpha_nav = alphabet_navigation(index_list) if alpha_nav: @@ -4169,7 +4164,7 @@ class EventPages(BasePage): # separate events by their type and then thier event handles for (evt_type, - data_list) in sort_event_types(self.dbase_, + data_list) in sort_event_types(self.report.database, event_types, event_handle_list): first = True @@ -4180,7 +4175,7 @@ class EventPages(BasePage): first_event = True for (sort_value, event_handle) in data_list: - event = self.dbase_.get_event_from_handle(event_handle) + event = self.report.database.get_event_from_handle(event_handle) _type = event.get_type() gid = event.get_gramps_id() if event.get_change_time() > ldatec: @@ -4192,13 +4187,13 @@ class EventPages(BasePage): # family event if int(_type) in _EVENTMAP: handle_list = set( - self.dbase_.find_backlink_handles( + self.report.database.find_backlink_handles( event_handle, include_classes=['Family', 'Person'])) else: handle_list = set( - self.dbase_.find_backlink_handles( + self.report.database.find_backlink_handles( event_handle, include_classes=['Person'])) if handle_list: @@ -4478,7 +4473,7 @@ class SurnameListPage(BasePage): # add alphabet navigation... # only if surname list not surname count if order_by == self.ORDER_BY_NAME: - index_list = get_first_letters(self.dbase_, ppl_handle_list, + index_list = get_first_letters(self.report.database, ppl_handle_list, _KEYPERSON) alpha_nav = alphabet_navigation(index_list) if alpha_nav is not None: @@ -4522,7 +4517,7 @@ class SurnameListPage(BasePage): with Html("tbody") as tbody: table += tbody - ppl_handle_list = sort_people(self.dbase_, ppl_handle_list) + ppl_handle_list = sort_people(self.report.database, ppl_handle_list) if order_by == self.ORDER_BY_COUNT: temp_list = {} for (surname, data_list) in ppl_handle_list: @@ -4632,7 +4627,7 @@ class IntroductionPage(BasePage): note_id = report.options['intronote'] if note_id: - note = self.dbase_.get_note_from_gramps_id(note_id) + note = self.report.database.get_note_from_gramps_id(note_id) note_text = self.get_note_format(note, False) # attach note @@ -4676,7 +4671,7 @@ class HomePage(BasePage): note_id = report.options['homenote'] if note_id: - note = self.dbase_.get_note_from_gramps_id(note_id) + note = self.report.database.get_note_from_gramps_id(note_id) note_text = self.get_note_format(note, False) # attach note @@ -4786,7 +4781,7 @@ class SourcePages(BasePage): # Sort the sources for handle in source_handles: - source = self.dbase_.get_source_from_handle(handle) + source = self.report.database.get_source_from_handle(handle) if source is not None: key = source.get_title() + source.get_author() key += str(source.get_gramps_id()) @@ -5074,7 +5069,7 @@ class MediaPages(BasePage): index = 1 for media_handle in sorted_media_handles: - media = self.dbase_.get_media_from_handle(media_handle) + media = self.report.database.get_media_from_handle(media_handle) if media: if media.get_change_time() > ldatec: ldatec = media.get_change_time() @@ -5106,7 +5101,7 @@ class MediaPages(BasePage): unused_media_handles = [] if self.create_unused_media: # add unused media - media_list = self.dbase_.get_media_handles() + media_list = self.report.database.get_media_handles() for media_ref in media_list: if isinstance(media_ref, bytes): media_handle = media_ref.decode("utf-8") @@ -5133,7 +5128,7 @@ class MediaPages(BasePage): Html("td", Html("h4", " "), inline=True) ) for media_handle in unused_media_handles: - media = self.dbase_.get_media_from_handle(media_handle) + media = self.report.database.get_media_from_handle(media_handle) gc.collect() # Reduce memory usage when many images. next_ = None if indx == total else \ unused_media_handles[indx] @@ -5222,7 +5217,7 @@ class MediaPages(BasePage): #note_only = True target_exists = False - copy_thumbnail(self.report, media_handle, media) + self.copy_thumbnail(media_handle, media) self.page_title = media.get_description() (mediapage, head, body) = self.write_header("%s - %s" % (_("Media"), @@ -5280,7 +5275,7 @@ class MediaPages(BasePage): # the user to have to await a large download # unnecessarily. Either way, set the display image # size as requested. - orig_image_path = media_path_full(self.dbase_, + orig_image_path = media_path_full(self.report.database, media.get_path()) #mtime = os.stat(orig_image_path).st_mtime (width, height) = image_size(orig_image_path) @@ -5339,7 +5334,7 @@ class MediaPages(BasePage): dirname = tempfile.mkdtemp() thmb_path = os.path.join(dirname, "document.png") if run_thumbnailer(mime_type, - media_path_full(self.dbase_, + media_path_full(self.report.database, media.get_path()), thmb_path, 320): try: @@ -5492,7 +5487,7 @@ class MediaPages(BasePage): to_dir = self.report.build_path('images', handle) newpath = os.path.join(to_dir, handle) + ext - fullpath = media_path_full(self.dbase_, photo.get_path()) + fullpath = media_path_full(self.report.database, photo.get_path()) if not os.path.isfile(fullpath): _WRONGMEDIAPATH.append([photo.get_gramps_id(), fullpath]) return None @@ -5538,11 +5533,11 @@ class ThumbnailPreviewPage(BasePage): self.photo_keys = sorted(self.report.obj_dict[Media], key=lambda x: sort_by_desc_and_gid( - self.dbase_.get_media_from_handle(x))) + self.report.database.get_media_from_handle(x))) if self.create_unused_media: # add unused media - media_list = self.dbase_.get_media_handles() + media_list = self.report.database.get_media_handles() unused_media_handles = [] for media_ref in media_list: if isinstance(media_ref, bytes): @@ -5554,14 +5549,14 @@ class ThumbnailPreviewPage(BasePage): media_list = [] for person_handle in self.photo_keys: - photo = self.dbase_.get_media_from_handle(person_handle) + photo = self.report.database.get_media_from_handle(person_handle) if photo: if photo.get_mime_type().startswith("image"): media_list.append((photo.get_description(), person_handle, photo)) if self.create_thumbs_only: - copy_thumbnail(self.report, person_handle, photo) + self.copy_thumbnail(person_handle, photo) media_list.sort(key=lambda x: SORT_KEY(x[0])) @@ -5929,7 +5924,7 @@ class ContactPage(BasePage): note_id = report.options['contactnote'] if note_id: - note = self.dbase_.get_note_from_gramps_id(note_id) + note = self.report.database.get_note_from_gramps_id(note_id) note_text = self.get_note_format(note, False) # attach note @@ -6039,7 +6034,7 @@ class PersonPages(BasePage): individuallist += Html("p", msg, id="description") # add alphabet navigation - index_list = get_first_letters(self.dbase_, ppl_handle_list, + index_list = get_first_letters(self.report.database, ppl_handle_list, _KEYPERSON) alpha_nav = alphabet_navigation(index_list) if alpha_nav is not None: @@ -6080,7 +6075,7 @@ class PersonPages(BasePage): tbody = Html("tbody") table += tbody - ppl_handle_list = sort_people(self.dbase_, ppl_handle_list) + ppl_handle_list = sort_people(self.report.database, ppl_handle_list) first = True for (surname, handle_list) in ppl_handle_list: @@ -6092,8 +6087,8 @@ class PersonPages(BasePage): first_surname = True for person_handle in sorted(handle_list, - key=lambda x: sort_on_name_and_grampsid(x, self.dbase_)): - person = self.dbase_.get_person_from_handle(person_handle) + key=self.sort_on_name_and_grampsid): + person = self.report.database.get_person_from_handle(person_handle) if person.get_change_time() > date: date = person.get_change_time() @@ -6132,7 +6127,7 @@ class PersonPages(BasePage): tcell = Html("td", class_="ColumnBirth", inline=True) trow += tcell - birth_date = _find_birth_date(self.dbase_, person) + birth_date = _find_birth_date(self.report.database, person) if birth_date is not None: if birth_date.fallback: tcell += Html('em', _dd.display(birth_date), @@ -6147,7 +6142,7 @@ class PersonPages(BasePage): tcell = Html("td", class_="ColumnDeath", inline=True) trow += tcell - death_date = _find_death_date(self.dbase_, person) + death_date = _find_death_date(self.report.database, person) if death_date is not None: if death_date.fallback: tcell += Html('em', _dd.display(death_date), @@ -6166,7 +6161,7 @@ class PersonPages(BasePage): tcell = () if family_list: for family_handle in family_list: - family = self.dbase_.get_family_from_handle( + family = self.report.database.get_family_from_handle( family_handle) partner_handle = ReportUtils.find_spouse(person, family) @@ -6197,17 +6192,17 @@ class PersonPages(BasePage): parent_handle_list = person.get_parent_family_handle_list() if parent_handle_list: parent_handle = parent_handle_list[0] - family = self.dbase_.get_family_from_handle( + family = self.report.database.get_family_from_handle( parent_handle) father_handle = family.get_father_handle() mother_handle = family.get_mother_handle() if father_handle: - father = self.dbase_.get_person_from_handle( + father = self.report.database.get_person_from_handle( father_handle) else: father = None if mother_handle: - mother = self.dbase_.get_person_from_handle( + mother = self.report.database.get_person_from_handle( mother_handle) else: mother = None @@ -6353,11 +6348,11 @@ class PersonPages(BasePage): # Individual Pages... if not self.inc_families: for handle in self.person.get_family_handle_list(): - family = self.dbase_.get_family_from_handle(handle) + family = self.report.database.get_family_from_handle(handle) if family: media_list += family.get_media_list() for evt_ref in family.get_event_ref_list(): - event = self.dbase_.get_event_from_handle( + event = self.report.database.get_event_from_handle( evt_ref.ref) media_list += event.get_media_list() @@ -6366,7 +6361,7 @@ class PersonPages(BasePage): # Individual Pages... if not self.inc_events: for evt_ref in self.person.get_primary_event_ref_list(): - event = self.dbase_.get_event_from_handle(evt_ref.ref) + event = self.report.database.get_event_from_handle(evt_ref.ref) if event: media_list += event.get_media_list() @@ -6784,15 +6779,14 @@ class PersonPages(BasePage): photolist = person.get_media_list() if photolist: photo_handle = photolist[0].get_reference_handle() - photo = self.dbase_.get_media_from_handle(photo_handle) + photo = self.report.database.get_media_from_handle(photo_handle) mime_type = photo.get_mime_type() if mime_type: region = self.media_ref_region_to_object(photo_handle, person) if region: # make a thumbnail of this region - newpath = copy_thumbnail(self.report, photo_handle, - photo, region) + newpath = self.copy_thumbnail(photo_handle, photo, region) # TODO. Check if build_url_fname can be used. newpath = "/".join(['..']*3 + [newpath]) if win(): @@ -6871,7 +6865,7 @@ class PersonPages(BasePage): box = [] if not handle: return box - person = self.dbase_.get_person_from_handle(handle) + person = self.report.database.get_person_from_handle(handle) box = self.draw_box(center2, col, person) box += self.connect_line(center1, center2, col) return box @@ -6918,7 +6912,7 @@ class PersonPages(BasePage): return tree gen_offset = int(max_size / pow(2, gen_nr+1)) if person_handle: - person = self.dbase_.get_person_from_handle(person_handle) + person = self.report.database.get_person_from_handle(person_handle) else: person = None if not person: @@ -6938,7 +6932,7 @@ class PersonPages(BasePage): line_offset = _XOFFSET + gen_nr*_WIDTH + (gen_nr-1)*_HGAP tree += self.extend_line(new_center, line_offset) - family = self.dbase_.get_family_from_handle(family_handle) + family = self.report.database.get_family_from_handle(family_handle) f_center = new_center-gen_offset f_handle = family.get_father_handle() @@ -7026,7 +7020,7 @@ class PersonPages(BasePage): childlist = family.get_child_ref_list() childlist = [child_ref.ref for child_ref in childlist] - children = add_birthdate(self.dbase_, childlist) + children = add_birthdate(self.report.database, childlist) if birthorder: children = sorted(children) @@ -7035,7 +7029,7 @@ class PersonPages(BasePage): if handle == self.person.get_handle(): child_ped(ol_html) elif handle: - child = self.dbase_.get_person_from_handle(handle) + child = self.report.database.get_person_from_handle(handle) if child: ol_html += Html("li") + self.pedigree_person(child) else: @@ -7058,15 +7052,15 @@ class PersonPages(BasePage): parent_handle_list = self.person.get_parent_family_handle_list() if parent_handle_list: parent_handle = parent_handle_list[0] - family = self.dbase_.get_family_from_handle(parent_handle) + family = self.report.database.get_family_from_handle(parent_handle) father_handle = family.get_father_handle() mother_handle = family.get_mother_handle() if mother_handle: - mother = self.dbase_.get_person_from_handle(mother_handle) + mother = self.report.database.get_person_from_handle(mother_handle) else: mother = None if father_handle: - father = self.dbase_.get_person_from_handle(father_handle) + father = self.report.database.get_person_from_handle(father_handle) else: father = None else: @@ -7153,7 +7147,7 @@ class PersonPages(BasePage): unordered = Html("ul") for notehandle in notelist: - note = self.dbase_.get_note_from_handle(notehandle) + note = self.report.database.get_note_from_handle(notehandle) if note: note_text = self.get_note_format(note, True) @@ -7216,14 +7210,14 @@ class PersonPages(BasePage): birth_date = Date.EMPTY birth_ref = self.person.get_birth_ref() if birth_ref: - birth = self.dbase_.get_event_from_handle(birth_ref.ref) + birth = self.report.database.get_event_from_handle(birth_ref.ref) if birth: birth_date = birth.get_date_object() if birth_date and birth_date is not Date.EMPTY: - alive = probably_alive(self.person, self.dbase_, Today()) + alive = probably_alive(self.person, self.report.database, Today()) - death_date = _find_death_date(self.dbase_, self.person) + death_date = _find_death_date(self.report.database, self.person) if not alive and death_date is not None: nyears = death_date - birth_date nyears.format(precision=3) @@ -7269,7 +7263,7 @@ class PersonPages(BasePage): table += tbody for evt_ref in event_ref_list: - event = self.dbase_.get_event_from_handle(evt_ref.ref) + event = self.report.database.get_event_from_handle(evt_ref.ref) if event: # display event row @@ -7359,7 +7353,7 @@ class PersonPages(BasePage): for child_ref in family.get_child_ref_list(): child_handle = child_ref.ref - child = self.dbase_.get_person_from_handle(child_handle) + child = self.report.database.get_person_from_handle(child_handle) if child: if child == self.person: reln = "" @@ -7370,7 +7364,7 @@ class PersonPages(BasePage): # routines to work. Depending on your definition of # sibling, we cannot necessarily guarantee that. sibling_type = self.rel_class.get_sibling_type( - self.dbase_, self.person, child) + self.report.database, self.person, child) reln = self.rel_class.get_sibling_relationship_string( sibling_type, self.person.gender, @@ -7416,10 +7410,10 @@ class PersonPages(BasePage): @param: table -- The html document to complete """ if parent_handle: - parent = self.dbase_.get_person_from_handle(parent_handle) + parent = self.report.database.get_person_from_handle(parent_handle) for parent_family_handle in parent.get_family_handle_list(): if parent_family_handle not in all_family_handles: - parent_family = self.dbase_.get_family_from_handle( + parent_family = self.report.database.get_family_from_handle( parent_family_handle) self.display_ind_parent_family(birthmother, birthfather, parent_family, table) @@ -7431,7 +7425,7 @@ class PersonPages(BasePage): """ center_person = self.report.database.get_person_from_gramps_id( self.report.options['pid']) - relationship = self.rel_class.get_one_relationship(self.dbase_, + relationship = self.rel_class.get_one_relationship(self.report.database, self.person, center_person) if relationship == "": # No relation to display @@ -7489,11 +7483,11 @@ class PersonPages(BasePage): all_family_handles = list(parent_list) (birthmother, birthfather) = self.rel_class.get_birth_parents( - self.dbase_, self.person) + self.report.database, self.person) first = True for family_handle in parent_list: - family = self.dbase_.get_family_from_handle(family_handle) + family = self.report.database.get_family_from_handle(family_handle) if family: # Display this family self.display_ind_parent_family( @@ -7530,10 +7524,10 @@ class PersonPages(BasePage): """ ped = [] for family_handle in self.person.get_family_handle_list(): - rel_family = self.dbase_.get_family_from_handle(family_handle) + rel_family = self.report.database.get_family_from_handle(family_handle) spouse_handle = ReportUtils.find_spouse(self.person, rel_family) if spouse_handle: - spouse = self.dbase_.get_person_from_handle(spouse_handle) + spouse = self.report.database.get_person_from_handle(spouse_handle) pedsp = (Html("li", class_="spouse") + self.pedigree_person(spouse) ) @@ -7545,7 +7539,7 @@ class PersonPages(BasePage): with Html("ol") as childol: pedsp += [childol] for child_ref in childlist: - child = self.dbase_.get_person_from_handle( + child = self.report.database.get_person_from_handle( child_ref.ref) if child: childol += (Html("li") + @@ -7979,16 +7973,6 @@ class NavWebReport(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu) - stdoptions.run_private_data_option(self, menu) - - livinginfo = self.options['living_people'] - yearsafterdeath = self.options['years_past_death'] - - if livinginfo != _INCLUDE_LIVING_VALUE: - self.database = LivingProxyDb(self.database, - livinginfo, - None, - yearsafterdeath) self.database = CacheProxyDb(self.database) From 898bfb4eae33539f54451af21829c46a29b43f9f Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Wed, 25 May 2016 16:18:48 -0400 Subject: [PATCH 08/11] narrativeweb: proxies and filters may hide objects --- gramps/plugins/webreport/narrativeweb.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gramps/plugins/webreport/narrativeweb.py b/gramps/plugins/webreport/narrativeweb.py index cfafd0c8c..97b45540a 100644 --- a/gramps/plugins/webreport/narrativeweb.py +++ b/gramps/plugins/webreport/narrativeweb.py @@ -8328,14 +8328,14 @@ class NavWebReport(Report): @param: bkref_handle -- The handle associated to this person """ person = self.database.get_person_from_handle(person_handle) - person_name = self.get_person_name(person) - person_fname = self.build_url_fname(person_handle, "ppl", - False) + self.ext - self.obj_dict[Person][person_handle] = (person_fname, person_name, - person.gramps_id) - self.bkref_dict[Person][person_handle].add((bkref_class, bkref_handle)) - if person: + person_name = self.get_person_name(person) + person_fname = self.build_url_fname(person_handle, "ppl", + False) + self.ext + self.obj_dict[Person][person_handle] = (person_fname, person_name, + person.gramps_id) + self.bkref_dict[Person][person_handle].add((bkref_class, bkref_handle)) + ############### Header section ############## for citation_handle in person.get_citation_list(): self._add_citation(citation_handle, Person, person_handle) From 1611340dca8a0b79624860e8a624a2c78af4c8f9 Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Thu, 26 May 2016 08:36:27 -0400 Subject: [PATCH 09/11] CacheProxyDb: use getattr() --- gramps/gen/proxy/cache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gramps/gen/proxy/cache.py b/gramps/gen/proxy/cache.py index 559ed504d..4b1ab1a41 100644 --- a/gramps/gen/proxy/cache.py +++ b/gramps/gen/proxy/cache.py @@ -45,7 +45,7 @@ class CacheProxyDb: If an attribute isn't found here, use the self.db version. """ - return self.db.__getattr__(attr) + return getattr(self.db, attr) def clear_cache(self, handle=None): """ From 2596aba875241d531d4f272fb0f337e14d556c18 Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Thu, 26 May 2016 08:40:03 -0400 Subject: [PATCH 10/11] Use CacheProxyDb on reports with LivingProxyDb --- gramps/plugins/drawreport/ancestortree.py | 2 ++ gramps/plugins/drawreport/descendtree.py | 2 ++ gramps/plugins/drawreport/fanchart.py | 2 ++ gramps/plugins/drawreport/statisticschart.py | 2 ++ gramps/plugins/drawreport/timeline.py | 2 ++ gramps/plugins/graph/gvfamilylines.py | 2 ++ gramps/plugins/graph/gvhourglass.py | 2 ++ gramps/plugins/graph/gvrelgraph.py | 2 ++ gramps/plugins/textreport/ancestorreport.py | 3 +++ gramps/plugins/textreport/descendreport.py | 2 ++ gramps/plugins/textreport/detancestralreport.py | 2 ++ gramps/plugins/textreport/detdescendantreport.py | 2 ++ gramps/plugins/textreport/endoflinereport.py | 2 ++ gramps/plugins/textreport/familygroup.py | 2 ++ gramps/plugins/textreport/indivcomplete.py | 2 ++ gramps/plugins/textreport/kinshipreport.py | 2 ++ gramps/plugins/textreport/placereport.py | 3 ++- gramps/plugins/textreport/recordsreport.py | 4 +++- gramps/plugins/textreport/summary.py | 2 ++ gramps/plugins/textreport/tagreport.py | 4 +++- 20 files changed, 43 insertions(+), 3 deletions(-) diff --git a/gramps/plugins/drawreport/ancestortree.py b/gramps/plugins/drawreport/ancestortree.py index 46054ddd8..ae15a18c3 100644 --- a/gramps/plugins/drawreport/ancestortree.py +++ b/gramps/plugins/drawreport/ancestortree.py @@ -47,6 +47,7 @@ from gramps.gen.plug.docgen import (FontStyle, ParagraphStyle, GraphicsStyle, FONT_SANS_SERIF, PARA_ALIGN_CENTER) from gramps.plugins.lib.libtreebase import * from gramps.plugins.lib.librecurse import AscendPerson +from gramps.gen.proxy import CacheProxyDb PT2CM = ReportUtils.pt2cm #cm2pt = ReportUtils.cm2pt @@ -550,6 +551,7 @@ class AncestorTree(Report): self._locale = self.set_locale(lang) stdoptions.run_private_data_option(self, options.menu) stdoptions.run_living_people_option(self, options.menu, self._locale) + self.database = CacheProxyDb(self.database) stdoptions.run_name_format_option(self, options.menu) self._nd = self._name_display diff --git a/gramps/plugins/drawreport/descendtree.py b/gramps/plugins/drawreport/descendtree.py index bfc39b663..cf4e4ed43 100644 --- a/gramps/plugins/drawreport/descendtree.py +++ b/gramps/plugins/drawreport/descendtree.py @@ -43,6 +43,7 @@ from gramps.gen.plug.report import utils as ReportUtils from gramps.gen.plug.docgen import (FontStyle, ParagraphStyle, GraphicsStyle, FONT_SANS_SERIF, PARA_ALIGN_CENTER) from gramps.plugins.lib.libtreebase import * +from gramps.gen.proxy import CacheProxyDb PT2CM = ReportUtils.pt2cm @@ -1286,6 +1287,7 @@ class DescendTree(Report): self._locale = self.set_locale(lang) stdoptions.run_private_data_option(self, options.menu) stdoptions.run_living_people_option(self, options.menu, self._locale) + self.database = CacheProxyDb(self.database) stdoptions.run_name_format_option(self, options.menu) self._nd = self._name_display diff --git a/gramps/plugins/drawreport/fanchart.py b/gramps/plugins/drawreport/fanchart.py index 515c9a288..2e4088bea 100644 --- a/gramps/plugins/drawreport/fanchart.py +++ b/gramps/plugins/drawreport/fanchart.py @@ -58,6 +58,7 @@ from gramps.gen.plug.report import stdoptions from gramps.gen.config import config from gramps.gen.utils.db import get_birth_or_fallback, get_death_or_fallback from gramps.gen.lib import EventType +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -179,6 +180,7 @@ class FanChart(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, rlocale) + self.database = CacheProxyDb(self.database) self.max_generations = menu.get_option_by_name('maxgen').get_value() self.circle = menu.get_option_by_name('circle').get_value() diff --git a/gramps/plugins/drawreport/statisticschart.py b/gramps/plugins/drawreport/statisticschart.py index 288493a1e..bbc045674 100644 --- a/gramps/plugins/drawreport/statisticschart.py +++ b/gramps/plugins/drawreport/statisticschart.py @@ -59,6 +59,7 @@ from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import stdoptions from gramps.gen.datehandler import parser from gramps.gen.display.place import displayer as place_displayer +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -745,6 +746,7 @@ class StatisticsChart(Report): stdoptions.run_private_data_option(self, menu) living_opt = stdoptions.run_living_people_option(self, menu, rlocale) + self.database = CacheProxyDb(self.database) get_option_by_name = menu.get_option_by_name get_value = lambda name: get_option_by_name(name).get_value() diff --git a/gramps/plugins/drawreport/timeline.py b/gramps/plugins/drawreport/timeline.py index c10000fb7..43a217642 100644 --- a/gramps/plugins/drawreport/timeline.py +++ b/gramps/plugins/drawreport/timeline.py @@ -45,6 +45,7 @@ from gramps.gen.plug.docgen import (FontStyle, ParagraphStyle, GraphicsStyle, from gramps.gen.sort import Sort from gramps.gen.config import config from gramps.gen.utils.db import get_birth_or_fallback, get_death_or_fallback +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -104,6 +105,7 @@ class TimeLine(Report): stdoptions.run_private_data_option(self, menu) living_opt = stdoptions.run_living_people_option(self, menu, rlocale) + self.database = CacheProxyDb(self.database) self.filter = menu.get_option_by_name('filter').get_filter() self.fil_name = "(%s)" % self.filter.get_name(rlocale) diff --git a/gramps/plugins/graph/gvfamilylines.py b/gramps/plugins/graph/gvfamilylines.py index a165f678c..b50ee987c 100644 --- a/gramps/plugins/graph/gvfamilylines.py +++ b/gramps/plugins/graph/gvfamilylines.py @@ -61,6 +61,7 @@ from gramps.gen.plug.menu import (NumberOption, ColorOption, BooleanOption, SurnameColorOption) from gramps.gen.utils.db import get_birth_or_fallback, get_death_or_fallback from gramps.gen.utils.location import get_main_location +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -319,6 +320,7 @@ class FamilyLinesReport(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, self._locale) + self.database = CacheProxyDb(self.database) self._db = self.database # initialize several convenient variables diff --git a/gramps/plugins/graph/gvhourglass.py b/gramps/plugins/graph/gvhourglass.py index 3b9249162..95e440036 100644 --- a/gramps/plugins/graph/gvhourglass.py +++ b/gramps/plugins/graph/gvhourglass.py @@ -48,6 +48,7 @@ from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import stdoptions from gramps.gen.datehandler import get_date from gramps.gen.utils.db import get_birth_or_fallback, get_death_or_fallback +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -86,6 +87,7 @@ class HourGlassReport(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, locale) + self.database = CacheProxyDb(self.database) self.__db = self.database self.__used_people = [] diff --git a/gramps/plugins/graph/gvrelgraph.py b/gramps/plugins/graph/gvrelgraph.py index bba67f35c..fc3d76579 100644 --- a/gramps/plugins/graph/gvrelgraph.py +++ b/gramps/plugins/graph/gvrelgraph.py @@ -60,6 +60,7 @@ from gramps.gen.utils.thumbnails import get_thumbnail_path from gramps.gen.relationship import get_relationship_calculator from gramps.gen.utils.db import get_birth_or_fallback, get_death_or_fallback from gramps.gen.display.place import displayer as place_displayer +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -130,6 +131,7 @@ class RelGraphReport(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, self._locale) + self.database = CacheProxyDb(self.database) self._db = self.database self.includeid = get_value('incid') diff --git a/gramps/plugins/textreport/ancestorreport.py b/gramps/plugins/textreport/ancestorreport.py index 899bb819d..e6125bda7 100644 --- a/gramps/plugins/textreport/ancestorreport.py +++ b/gramps/plugins/textreport/ancestorreport.py @@ -48,6 +48,7 @@ from gramps.gen.plug.report import utils as ReportUtils from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import stdoptions from gramps.plugins.lib.libnarrate import Narrator +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -110,6 +111,8 @@ class AncestorReport(Report): stdoptions.run_name_format_option(self, menu) + self.database = CacheProxyDb(self.database) + self.__narrator = Narrator(self.database, use_fulldate=True, nlocale=rlocale) diff --git a/gramps/plugins/textreport/descendreport.py b/gramps/plugins/textreport/descendreport.py index 7104f9ef4..15d5fa554 100644 --- a/gramps/plugins/textreport/descendreport.py +++ b/gramps/plugins/textreport/descendreport.py @@ -55,6 +55,7 @@ from gramps.gen.sort import Sort from gramps.gen.utils.db import (get_birth_or_fallback, get_death_or_fallback, get_marriage_or_fallback, get_divorce_or_fallback) +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -341,6 +342,7 @@ class DescendantReport(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, self._locale) + self.database = CacheProxyDb(self.database) self.max_generations = menu.get_option_by_name('gen').get_value() pid = menu.get_option_by_name('pid').get_value() diff --git a/gramps/plugins/textreport/detancestralreport.py b/gramps/plugins/textreport/detancestralreport.py index 37fa18303..ceab5651a 100644 --- a/gramps/plugins/textreport/detancestralreport.py +++ b/gramps/plugins/textreport/detancestralreport.py @@ -59,6 +59,7 @@ from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import stdoptions from gramps.plugins.lib.libnarrate import Narrator from gramps.gen.display.place import displayer as place_displayer +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -124,6 +125,7 @@ class DetAncestorReport(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, self._locale) + self.database = CacheProxyDb(self.database) self._db = self.database self.max_generations = get_value('gen') diff --git a/gramps/plugins/textreport/detdescendantreport.py b/gramps/plugins/textreport/detdescendantreport.py index aaab0042a..b01ff2621 100644 --- a/gramps/plugins/textreport/detdescendantreport.py +++ b/gramps/plugins/textreport/detdescendantreport.py @@ -59,6 +59,7 @@ from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import stdoptions from gramps.plugins.lib.libnarrate import Narrator from gramps.gen.display.place import displayer as place_displayer +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -136,6 +137,7 @@ class DetDescendantReport(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, self._locale) + self.database = CacheProxyDb(self.database) self.db = self.database self.max_generations = get_value('gen') diff --git a/gramps/plugins/textreport/endoflinereport.py b/gramps/plugins/textreport/endoflinereport.py index 2df9e11e8..2e65f7519 100644 --- a/gramps/plugins/textreport/endoflinereport.py +++ b/gramps/plugins/textreport/endoflinereport.py @@ -46,6 +46,7 @@ from gramps.gen.plug.report import utils as ReportUtils from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import stdoptions from gramps.gen.datehandler import get_date +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -80,6 +81,7 @@ class EndOfLineReport(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, rlocale) + self.database = CacheProxyDb(self.database) pid = menu.get_option_by_name('pid').get_value() self.center_person = self.database.get_person_from_gramps_id(pid) diff --git a/gramps/plugins/textreport/familygroup.py b/gramps/plugins/textreport/familygroup.py index a88ed6a82..154cf034d 100644 --- a/gramps/plugins/textreport/familygroup.py +++ b/gramps/plugins/textreport/familygroup.py @@ -49,6 +49,7 @@ from gramps.gen.plug.docgen import (IndexMark, FontStyle, ParagraphStyle, FONT_SANS_SERIF, FONT_SERIF, INDEX_TYPE_TOC, PARA_ALIGN_CENTER) from gramps.gen.display.place import displayer as place_displayer +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -89,6 +90,7 @@ class FamilyGroup(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, self._locale) + self.database = CacheProxyDb(self.database) self.db = self.database self.filter = menu.get_option_by_name('filter').get_filter() diff --git a/gramps/plugins/textreport/indivcomplete.py b/gramps/plugins/textreport/indivcomplete.py index e5c8d6d6c..6f916465e 100644 --- a/gramps/plugins/textreport/indivcomplete.py +++ b/gramps/plugins/textreport/indivcomplete.py @@ -57,6 +57,7 @@ from gramps.gen.plug.report import endnotes as Endnotes from gramps.gen.plug.report import stdoptions from gramps.gen.utils.file import media_path_full from gramps.gen.utils.lds import TEMPLES +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -123,6 +124,7 @@ class IndivCompleteReport(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, self._locale) + self.database = CacheProxyDb(self.database) self._db = self.database self.use_pagebreak = menu.get_option_by_name('pageben').get_value() diff --git a/gramps/plugins/textreport/kinshipreport.py b/gramps/plugins/textreport/kinshipreport.py index 5cd718333..ed5c0e143 100644 --- a/gramps/plugins/textreport/kinshipreport.py +++ b/gramps/plugins/textreport/kinshipreport.py @@ -48,6 +48,7 @@ from gramps.gen.plug.report import utils as ReportUtils from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import stdoptions from gramps.gen.utils.db import get_birth_or_fallback, get_death_or_fallback +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -88,6 +89,7 @@ class KinshipReport(Report): stdoptions.run_private_data_option(self, menu) stdoptions.run_living_people_option(self, menu, rlocale) + self.database = CacheProxyDb(self.database) self.__db = self.database self.max_descend = menu.get_option_by_name('maxdescend').get_value() diff --git a/gramps/plugins/textreport/placereport.py b/gramps/plugins/textreport/placereport.py index 4a6ef880d..d1c12eb16 100644 --- a/gramps/plugins/textreport/placereport.py +++ b/gramps/plugins/textreport/placereport.py @@ -50,7 +50,7 @@ from gramps.gen.utils.location import get_location_list from gramps.gen.display.place import displayer as place_displayer from gramps.gen.lib import PlaceType from gramps.gen.errors import ReportError -from gramps.gen.proxy import LivingProxyDb +from gramps.gen.proxy import LivingProxyDb, CacheProxyDb class PlaceReport(Report): """ @@ -87,6 +87,7 @@ class PlaceReport(Report): stdoptions.run_private_data_option(self, menu) living_opt = stdoptions.run_living_people_option(self, menu, rlocale) + self.database = CacheProxyDb(self.database) self._lv = menu.get_option_by_name('living_people').get_value() for (value, description) in living_opt.get_items(xml_items=True): diff --git a/gramps/plugins/textreport/recordsreport.py b/gramps/plugins/textreport/recordsreport.py index 1af81cd03..72ae4f19c 100644 --- a/gramps/plugins/textreport/recordsreport.py +++ b/gramps/plugins/textreport/recordsreport.py @@ -49,7 +49,7 @@ from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import stdoptions from gramps.gen.lib import Span from gramps.gen.errors import ReportError -from gramps.gen.proxy import LivingProxyDb +from gramps.gen.proxy import LivingProxyDb, CacheProxyDb #------------------------------------------------------------------------ # @@ -100,6 +100,8 @@ class RecordsReport(Report): self._nf = stdoptions.run_name_format_option(self, menu) + self.database = CacheProxyDb(self.database) + def write_report(self): """ Build the actual report. diff --git a/gramps/plugins/textreport/summary.py b/gramps/plugins/textreport/summary.py index 34b9ac8d8..474f7184e 100644 --- a/gramps/plugins/textreport/summary.py +++ b/gramps/plugins/textreport/summary.py @@ -49,6 +49,7 @@ from gramps.gen.plug.docgen import (IndexMark, FontStyle, ParagraphStyle, PARA_ALIGN_CENTER) from gramps.gen.utils.file import media_path_full from gramps.gen.datehandler import get_date +from gramps.gen.proxy import CacheProxyDb #------------------------------------------------------------------------ # @@ -79,6 +80,7 @@ class SummaryReport(Report): stdoptions.run_private_data_option(self, options.menu) stdoptions.run_living_people_option(self, options.menu, rlocale) + self.database = CacheProxyDb(self.database) self.__db = self.database def write_report(self): diff --git a/gramps/plugins/textreport/tagreport.py b/gramps/plugins/textreport/tagreport.py index 8b7bb4939..0a2fdb466 100644 --- a/gramps/plugins/textreport/tagreport.py +++ b/gramps/plugins/textreport/tagreport.py @@ -52,7 +52,7 @@ from gramps.gen.errors import ReportError from gramps.gen.datehandler import get_date from gramps.gen.utils.db import get_participant_from_event from gramps.gen.display.place import displayer as place_displayer -from gramps.gen.proxy import LivingProxyDb +from gramps.gen.proxy import LivingProxyDb, CacheProxyDb #------------------------------------------------------------------------ # @@ -104,6 +104,8 @@ class TagReport(Report): stdoptions.run_name_format_option(self, menu) + self.database = CacheProxyDb(self.database) + def write_report(self): self.doc.start_paragraph("TR-Title") # feature request 2356: avoid genitive form From e2a5fe8e1243afdc58cdd2d81cdb7dc093f78ee0 Mon Sep 17 00:00:00 2001 From: Nick Hall Date: Thu, 26 May 2016 18:18:33 +0100 Subject: [PATCH 11/11] Use CSS to fade background colour in ValidatableMaskedEntry --- gramps/gui/widgets/validatedmaskedentry.py | 225 ++++----------------- 1 file changed, 39 insertions(+), 186 deletions(-) diff --git a/gramps/gui/widgets/validatedmaskedentry.py b/gramps/gui/widgets/validatedmaskedentry.py index 365a94f33..341a9fbc1 100644 --- a/gramps/gui/widgets/validatedmaskedentry.py +++ b/gramps/gui/widgets/validatedmaskedentry.py @@ -43,7 +43,6 @@ from gi.repository import GObject from gi.repository import GLib from gi.repository import Gdk from gi.repository import Gtk -from gi.repository import GdkPixbuf from gi.repository import Pango #------------------------------------------------------------------------- @@ -63,111 +62,6 @@ from .undoableentry import UndoableEntry # #============================================================================ -class FadeOut(GObject.GObject): - """ - I am a helper class to draw the fading effect of the background - Call my methods :meth:`start` and :meth:`stop` to control the fading. - """ - __gsignals__ = { - 'done': (GObject.SignalFlags.RUN_FIRST, - None, - ()), - 'color-changed': (GObject.SignalFlags.RUN_FIRST, - None, - (Gdk.Color, )), - } - - # How long time it'll take before we start (in ms) - COMPLAIN_DELAY = 500 - - MERGE_COLORS_DELAY = 100 - - def __init__(self, widget, err_color = "#ffd5d5"): - GObject.GObject.__init__(self) - self.ERROR_COLOR = err_color - self._widget = widget - self._start_color = None - self._background_timeout_id = -1 - self._countdown_timeout_id = -1 - self._done = False - - def _merge_colors(self, src_color, dst_color, steps=10): - """ - Change the background of widget from src_color to dst_color - in the number of steps specified - """ - ##_LOG.debug('_merge_colors: %s -> %s' % (src_color, dst_color)) - - rs, gs, bs = src_color.red, src_color.green, src_color.blue - rd, gd, bd = dst_color.red, dst_color.green, dst_color.blue - rinc = (rd - rs) / float(steps) - ginc = (gd - gs) / float(steps) - binc = (bd - bs) / float(steps) - for dummy in range(steps): - rs += rinc - gs += ginc - bs += binc - col = Gdk.color_parse("#%02X%02X%02X" % (int(rs) >> 8, - int(gs) >> 8, - int(bs) >> 8)) - self.emit('color-changed', col) - yield True - - self.emit('done') - self._background_timeout_id = -1 - self._done = True - yield False - - def _start_merging(self): - # If we changed during the delay - if self._background_timeout_id != -1: - ##_LOG.debug('_start_merging: Already running') - return - - ##_LOG.debug('_start_merging: Starting') - generator = self._merge_colors(self._start_color, - Gdk.color_parse(self.ERROR_COLOR)) - self._background_timeout_id = ( - GLib.timeout_add(FadeOut.MERGE_COLORS_DELAY, generator.__next__)) - self._countdown_timeout_id = -1 - - def start(self, color): - """ - Schedules a start of the countdown. - - :param color: initial background color - :returns: True if we could start, False if was already in progress - """ - if self._background_timeout_id != -1: - ##_LOG.debug('start: Background change already running') - return False - if self._countdown_timeout_id != -1: - ##_LOG.debug('start: Countdown already running') - return False - if self._done: - ##_LOG.debug('start: Not running, already set') - return False - - self._start_color = color - ##_LOG.debug('start: Scheduling') - self._countdown_timeout_id = GLib.timeout_add( - FadeOut.COMPLAIN_DELAY, self._start_merging) - - return True - - def stop(self): - """Stops the fadeout and restores the background color""" - ##_LOG.debug('Stopping') - if self._background_timeout_id != -1: - GLib.source_remove(self._background_timeout_id) - self._background_timeout_id = -1 - if self._countdown_timeout_id != -1: - GLib.source_remove(self._countdown_timeout_id) - self._countdown_timeout_id = -1 - - self._widget.update_background(self._start_color, unset=True) - self._done = False - (DIRECTION_LEFT, DIRECTION_RIGHT) = (1, -1) (INPUT_ASCII_LETTER, @@ -1013,52 +907,6 @@ class MaskedEntry(UndoableEntry): def set_stock(self, icon_name): self.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon_name) - def update_background(self, color, unset=False): - maxvalcol = 65535. - if color: - red = int(color.red/ maxvalcol*255) - green = int(color.green/ maxvalcol*255) - blue = int(color.blue/ maxvalcol*255) - rgba = Gdk.RGBA() - Gdk.RGBA.parse(rgba, 'rgb(%f,%f,%f)'%(red, green, blue)) - self.override_background_color(Gtk.StateFlags.NORMAL | - Gtk.StateFlags.ACTIVE | Gtk.StateFlags.SELECTED | - Gtk.StateFlags.FOCUSED, rgba) - #GTK 3: workaround, background not changing in themes, use symbolic - self.override_symbolic_color('bg_color', rgba) - self.override_symbolic_color('base_color', rgba) - self.override_symbolic_color('theme_bg_color', rgba) - self.override_symbolic_color('theme_base_color', rgba) - ##self.get_window().set_background_rgba(rgba) - pango_context = self.get_layout().get_context() - font_description = pango_context.get_font_description() - if unset: - font_description.set_weight(Pango.Weight.NORMAL) - else: - font_description.set_weight(Pango.Weight.BOLD) - self.override_font(font_description) - else: - self.override_background_color(Gtk.StateFlags.NORMAL | - Gtk.StateFlags.ACTIVE | Gtk.StateFlags.SELECTED | - Gtk.StateFlags.FOCUSED, None) - # Setting the following to None causes an error (bug #6353). - #self.override_symbolic_color('bg_color', None) - #self.override_symbolic_color('base_color', None) - #self.override_symbolic_color('theme_bg_color', None) - #self.override_symbolic_color('theme_base_color', None) - pango_context = self.get_layout().get_context() - font_description = pango_context.get_font_description() - font_description.set_weight(Pango.Weight.NORMAL) - self.override_font(font_description) - - def get_background(self): - backcol = self.get_style_context().get_background_color(Gtk.StateType.NORMAL) - bcol= Gdk.Color.parse('#fff')[1] - bcol.red = int(backcol.red * 65535) - bcol.green = int(backcol.green * 65535) - bcol.blue = int(backcol.blue * 65535) - return bcol - # Gtk.EntryCompletion convenience function def prefill(self, itemdata, sort=False): @@ -1091,6 +939,7 @@ class MaskedEntry(UndoableEntry): VALIDATION_ICON_WIDTH = 16 MANDATORY_ICON = 'dialog-information' ERROR_ICON = 'process-stop' +FADE_TIME = 2500 class ValidatableMaskedEntry(MaskedEntry): """ @@ -1132,7 +981,7 @@ class ValidatableMaskedEntry(MaskedEntry): #allowed_data_types = (basestring, datetime.date, datetime.time, #datetime.datetime, object) + number - def __init__(self, data_type=None, err_color = "#ffd5d5", error_icon=ERROR_ICON): + def __init__(self, data_type=None, err_color="pink", error_icon=ERROR_ICON): self.data_type = None self.mandatory = False self.error_icon = error_icon @@ -1142,8 +991,19 @@ class ValidatableMaskedEntry(MaskedEntry): self._valid = True self._def_error_msg = None - self._fade = FadeOut(self, err_color) - self._fade.connect('color-changed', self._on_fadeout__color_changed) + + self.__fade_tag = None + provider = Gtk.CssProvider() + css = '.fade {\n' + css += ' background: {};\n'.format(err_color) + css += ' transition: background {:d}ms linear;\n'.format(FADE_TIME) + css += '}' + css += '.bg {\n' + css += ' background: {};\n'.format(err_color) + css += '}' + provider.load_from_data(css.encode('utf8')) + context = self.get_style_context() + context.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) # FIXME put data type support back #self.set_property('data-type', data_type) @@ -1265,10 +1125,18 @@ class ValidatableMaskedEntry(MaskedEntry): reset the background color """ ##_LOG.debug('Setting state for %s to VALID' % self.model_attribute) + if self.is_valid(): + return + self._set_valid_state(True) - self._fade.stop() - self.set_pixbuf(None) + if self.__fade_tag is not None: + GLib.source_remove(self.__fade_tag) + self.__fade_tag = None + self.set_stock(None) + context = self.get_style_context() + context.remove_class('fade') + context.remove_class('bg') def set_invalid(self, text=None, fade=True): """ @@ -1278,6 +1146,8 @@ class ValidatableMaskedEntry(MaskedEntry): :param fade: if we should fade the background """ ##_LOG.debug('Setting state for %s to INVALID' % self.model_attribute) + if not self.is_valid(): + return self._set_valid_state(False) @@ -1306,29 +1176,13 @@ class ValidatableMaskedEntry(MaskedEntry): self.set_tooltip(text) - if not fade: - if self.error_icon: - self.set_stock(self.error_icon) - self.update_background(Gdk.color_parse(self._fade.ERROR_COLOR)) - return - - # When the fading animation is finished, set the error icon - # We don't need to check if the state is valid, since stop() - # (which removes this timeout) is called as soon as the user - # types valid data. - def done(fadeout, c): - if self.error_icon: - self.set_stock(self.error_icon) - self.queue_draw() - fadeout.disconnect(c.signal_id) - - class SignalContainer: - pass - c = SignalContainer() - c.signal_id = self._fade.connect('done', done, c) - - if self._fade.start(self.get_background()): - self.set_pixbuf(None) + context = self.get_style_context() + if fade: + self.__fade_tag = GLib.timeout_add(FADE_TIME, self.__fade_finished) + context.add_class('fade') + else: + self.set_stock(self.error_icon) + context.add_class('bg') def set_blank(self): """ @@ -1340,9 +1194,7 @@ class ValidatableMaskedEntry(MaskedEntry): if self.mandatory: self.set_stock(MANDATORY_ICON) - self.queue_draw() self.set_tooltip(_('This field is mandatory')) - self._fade.stop() valid = False else: valid = True @@ -1377,10 +1229,11 @@ class ValidatableMaskedEntry(MaskedEntry): self.emit('validation-changed', state) self._valid = state - # Callbacks - - def _on_fadeout__color_changed(self, fadeout, color): - self.update_background(color) + def __fade_finished(self): + """Set error icon after fade has finished.""" + self.__fade_tag = None + self.set_stock(self.error_icon) + return False def main(args):