From c91b53f0c498fb201e2db72f4dd9ea838893289c Mon Sep 17 00:00:00 2001 From: Tim G L Lyons Date: Sun, 20 Jan 2013 15:11:06 +0000 Subject: [PATCH] 0005088: Narrated Web Site Report sort order different Windows vs Linux. Initial commit to resolve the issues on Linux and Mac (provided in both cases PyICU is installed). Windows still needs to be tested, and there may still be some other uses of strxfrm (or strcoll) that need to be fixed. svn: r21175 --- gramps/gen/utils/cast.py | 59 +++++++++++++++----- gramps/gui/views/treemodels/flatbasemodel.py | 24 ++++---- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/gramps/gen/utils/cast.py b/gramps/gen/utils/cast.py index 1f7d19416..f9e7fa1f8 100644 --- a/gramps/gen/utils/cast.py +++ b/gramps/gen/utils/cast.py @@ -31,9 +31,11 @@ Utility functions to cast types # Python modules # #------------------------------------------------------------------------- +import os import locale import sys - +import logging +LOG = logging.getLogger(".") #------------------------------------------------------------------------- # # Gramps modules @@ -42,19 +44,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.