diff --git a/gramps/gen/utils/cast.py b/gramps/gen/utils/cast.py index 1f7d19416..697af3751 100644 --- a/gramps/gen/utils/cast.py +++ b/gramps/gen/utils/cast.py @@ -31,8 +31,11 @@ Utility functions to cast types # Python modules # #------------------------------------------------------------------------- +import os import locale import sys +import logging +LOG = logging.getLogger(".") #------------------------------------------------------------------------- # @@ -42,19 +45,48 @@ import sys from ..datehandler import codeset from ..constfunc import conv_to_unicode, conv_to_unicode_direct, UNITYPE, STRTYPE -""" -strxfrm needs it's unicode argument correctly cast before used. -""" -if sys.version_info[0] < 3: - conv_unicode_tosrtkey = lambda x: locale.strxfrm(x.encode(codeset, 'replace')) -else: - conv_unicode_tosrtkey = lambda x: locale.strxfrm(x) - -if codeset == 'UTF-8': - conv_str_tosrtkey = lambda x: locale.strxfrm(x) -else: - conv_str_tosrtkey = lambda x: locale.strxfrm( - conv_to_unicode(x,'UTF-8').encode(codeset, 'replace')) +try: + import PyICU + if os.environ.has_key("LC_COLLATE"): + collation = os.environ['LC_COLLATE'] + else: + collation = os.environ["LANG"] + language_and_country = collation.rsplit('.', 1)[0] + if language_and_country in PyICU.Collator.getAvailableLocales().keys(): + loc = language_and_country + else: + language = collation.rsplit('_', 1)[0] + if language in PyICU.Collator.getAvailableLocales().keys(): + LOG.warn(_("Language and country %s not supported by ICU: " + "but language %s is supported and will be used" % + (language_and_country, language))) + loc = language + else: + LOG.warn(_("Neither Language and country %s nor language %s " + "supported by ICU: using en_GB" % + (language_and_country, language))) + loc = "en_GB" + + collator = PyICU.Collator.createInstance(PyICU.Locale(loc)) + # on ICU, the functions need to receive unicode + conv_unicode_tosrtkey = lambda x: collator.getCollationKey( + x).getByteArray() + conv_str_tosrtkey = lambda x: collator.getCollationKey( + x.decode("UTF-8")).getByteArray() +except: + """ + strxfrm needs it's unicode argument correctly cast before used. + """ + if sys.version_info[0] < 3: + conv_unicode_tosrtkey = lambda x: locale.strxfrm(x.encode(codeset, 'replace')) + else: + conv_unicode_tosrtkey = lambda x: locale.strxfrm(x) + + if codeset == 'UTF-8': + conv_str_tosrtkey = lambda x: locale.strxfrm(x) + else: + conv_str_tosrtkey = lambda x: locale.strxfrm( + conv_to_unicode(x,'UTF-8').encode(codeset, 'replace')) def conv_tosrtkey(value): if isinstance(value, UNITYPE): diff --git a/gramps/gui/views/treemodels/flatbasemodel.py b/gramps/gui/views/treemodels/flatbasemodel.py index b859843ff..0bf1993da 100644 --- a/gramps/gui/views/treemodels/flatbasemodel.py +++ b/gramps/gui/views/treemodels/flatbasemodel.py @@ -112,8 +112,8 @@ class FlatNodeMap(object): the path, and a dictionary mapping hndl to index. To obtain index given a path, method real_index() is available - ..Note: If a string sortkey is used, apply conv_unicode_tosrtkey - on it , so as to have localized sort + ..Note: conv_unicode_tosrtkey is applied to the underlying sort key, + so as to have localized sort """ def __init__(self): @@ -456,6 +456,8 @@ class FlatBaseModel(GObject.Object, Gtk.TreeModel): """ The base class for all flat treeview models. It keeps a FlatNodeMap, and obtains data from database as needed + ..Note: conv_unicode_tosrtkey is applied to the underlying sort key, + so as to have localized sort """ def __init__(self, db, scol=0, order=Gtk.SortType.ASCENDING, @@ -478,9 +480,9 @@ class FlatBaseModel(GObject.Object, Gtk.TreeModel): self.sort_map = [ f for f in sort_map if f[0]] #we need the model col, that corresponds with scol col = self.sort_map[scol][1] - self.sort_func = self.smap[col] else: - self.sort_func = self.smap[scol] + col = scol + self.sort_func = lambda x: conv_unicode_tosrtkey(self.smap[col](x)) self.sort_col = scol self.skip = skip self._in_build = False @@ -577,15 +579,11 @@ class FlatBaseModel(GObject.Object, Gtk.TreeModel): Return the (sort_key, handle) list of all data that can maximally be shown. This list is sorted ascending, via localized string sort. - conv_unicode_tosrtkey which uses strxfrm """ # use cursor as a context manager with self.gen_cursor() as cursor: - #loop over database and store the sort field, and the handle, and - #allow for a third iter - return sorted((list(map(conv_tosrtkey, - self.sort_func(data))), handle2internal(key)) - for key, data in cursor) + #loop over database and store the sort field, and the handle + return sorted((self.sort_func(data), key) for key, data in cursor) def _rebuild_search(self, ignore=None): """ function called when view must be build, given a search text @@ -656,8 +654,7 @@ class FlatBaseModel(GObject.Object, Gtk.TreeModel): if self.node_map.get_path_from_handle(handle) is not None: return # row is already displayed data = self.map(handle) - insert_val = (list(map(conv_tosrtkey, self.sort_func(data))), - handle) + insert_val = (self.sort_func(data), handle) if not self.search or \ (self.search and self.search.match(handle, self.db)): #row needs to be added to the model @@ -692,8 +689,7 @@ class FlatBaseModel(GObject.Object, Gtk.TreeModel): return # row is not currently displayed self.clear_cache(handle) oldsortkey = self.node_map.get_sortkey(handle) - newsortkey = list(map(conv_tosrtkey, self.sort_func(self.map( - handle)))) + newsortkey = self.sort_func(self.map(handle)) if oldsortkey is None or oldsortkey != newsortkey: #or the changed object is not present in the view due to filtering #or the order of the object must change.