Meinert Jordan has proposed merging lp:~m2j/openlp/bug-687638 into lp:openlp.
Requested reviews: OpenLP Core (openlp-core) For more details, see: https://code.launchpad.net/~m2j/openlp/bug-687638/+merge/89098 I've splitted a previous merge request. This one contains only ICU integration: Bug #687638 locale.strcoll does not work correct on Windows with utf-8 [http://sgehrig.wordpress.com/2008/12/08/update-on-strcoll-utf-8-issue/]. The performance ICU is similar to locale.strcoll on Linux (12% faster for a English word list, 10% slower on a German one) ICU is said to give better results and makes less cross platform troubles. I've implemented it to be ued if available. Fallback is the POSIX locale.strcoll. It seems to be only necessary on Windows, so I suggest to include it only in Windows builds. -- https://code.launchpad.net/~m2j/openlp/bug-687638/+merge/89098 Your team OpenLP Core is requested to review the proposed merge of lp:~m2j/openlp/bug-687638 into lp:openlp.
=== modified file 'openlp/core/ui/exceptionform.py' --- openlp/core/ui/exceptionform.py 2011-12-27 10:33:55 +0000 +++ openlp/core/ui/exceptionform.py 2012-01-18 18:04:32 +0000 @@ -81,6 +81,11 @@ WEBKIT_VERSION = QtWebKit.qWebKitVersion() except AttributeError: WEBKIT_VERSION = u'-' +try: + import icu + ICU_VERSION = u'OK' +except ImportError: + ICU_VERSION = u'-' from openlp.core.lib import translate, SettingsManager @@ -125,7 +130,8 @@ u'PyEnchant: %s\n' % ENCHANT_VERSION + \ u'PySQLite: %s\n' % SQLITE_VERSION + \ u'Mako: %s\n' % MAKO_VERSION + \ - u'pyUNO bridge: %s\n' % UNO_VERSION + u'pyUNO bridge: %s\n' % UNO_VERSION + \ + u'PyICU: %s\n' % ICU_VERSION if platform.system() == u'Linux': if os.environ.get(u'KDE_FULL_SESSION') == u'true': system = system + u'Desktop: KDE SC\n' === modified file 'openlp/core/ui/thememanager.py' --- openlp/core/ui/thememanager.py 2012-01-04 17:19:49 +0000 +++ openlp/core/ui/thememanager.py 2012-01-18 18:04:32 +0000 @@ -29,7 +29,6 @@ import zipfile import shutil import logging -import locale import re from xml.etree.ElementTree import ElementTree, XML @@ -44,7 +43,8 @@ context_menu_action, context_menu_separator from openlp.core.theme import Theme from openlp.core.ui import FileRenameForm, ThemeForm -from openlp.core.utils import AppLocation, delete_file, get_filesystem_encoding +from openlp.core.utils import AppLocation, delete_file, \ + get_filesystem_encoding, get_local_collator log = logging.getLogger(__name__) @@ -459,7 +459,7 @@ # Sort the themes by its name considering language specific characters. # lower() is needed for windows! files.sort(key=lambda filename: unicode(filename).lower(), - cmp=locale.strcoll) + cmp=get_local_collator) # now process the file list of png files for name in files: # check to see file is in theme root directory === modified file 'openlp/core/utils/__init__.py' --- openlp/core/utils/__init__.py 2011-12-27 10:33:55 +0000 +++ openlp/core/utils/__init__.py 2012-01-18 18:04:32 +0000 @@ -33,6 +33,7 @@ import sys import time import urllib2 +import locale from datetime import datetime from subprocess import Popen, PIPE @@ -45,6 +46,17 @@ except ImportError: XDG_BASE_AVAILABLE = False +LOCALE_COLLATOR = locale.strcoll +try: + import icu + try: + icu_locale = icu.Locale(locale.getlocale()[0]) + LOCALE_COLLATOR = icu.Collator.createInstance(icu_locale).compare + except icu.InvalidArgsError: + pass +except ImportError: + pass + import openlp from openlp.core.lib import Receiver, translate, check_directory_exists @@ -482,10 +494,16 @@ return resolver.resolve(u'uno:socket,host=localhost,port=2002;' \ + u'urp;StarOffice.ComponentContext') +def get_local_collator(string1, string2): + """ + Returns a collator for locale aware string sorting. + """ + return LOCALE_COLLATOR(string1, string2) + from languagemanager import LanguageManager from actions import ActionList __all__ = [u'AppLocation', u'get_application_version', u'check_latest_version', u'add_actions', u'get_filesystem_encoding', u'LanguageManager', u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance', - u'delete_file', u'clean_filename'] + u'get_local_collator', u'delete_file', u'clean_filename'] === modified file 'openlp/plugins/bibles/forms/bibleimportform.py' --- openlp/plugins/bibles/forms/bibleimportform.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/bibles/forms/bibleimportform.py 2012-01-18 18:04:32 +0000 @@ -30,7 +30,6 @@ import logging import os import os.path -import locale from PyQt4 import QtCore, QtGui @@ -38,7 +37,7 @@ from openlp.core.lib.db import delete_database from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings -from openlp.core.utils import AppLocation +from openlp.core.utils import AppLocation, get_local_collator from openlp.plugins.bibles.lib.manager import BibleFormat from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename @@ -522,7 +521,7 @@ """ self.webTranslationComboBox.clear() bibles = self.web_bible_list[index].keys() - bibles.sort(cmp=locale.strcoll) + bibles.sort(cmp=get_local_collator) self.webTranslationComboBox.addItems(bibles) def onOsisBrowseButtonClicked(self): === modified file 'openlp/plugins/bibles/lib/mediaitem.py' --- openlp/plugins/bibles/lib/mediaitem.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/bibles/lib/mediaitem.py 2012-01-18 18:04:32 +0000 @@ -26,7 +26,6 @@ ############################################################################### import logging -import locale from PyQt4 import QtCore, QtGui @@ -36,6 +35,7 @@ from openlp.core.lib.ui import UiStrings, add_widget_completer, \ media_item_combo_box, critical_error_message_box, \ find_and_set_in_combo_box, build_icon +from openlp.core.utils import get_local_collator from openlp.plugins.bibles.forms import BibleImportForm from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \ VerseReferenceList, get_reference_match @@ -373,7 +373,7 @@ self.advancedSecondComboBox.addItem(u'') # Get all bibles and sort the list. bibles = self.plugin.manager.get_bibles().keys() - bibles.sort(cmp=locale.strcoll) + bibles.sort(cmp=get_local_collator) # Load the bibles into the combo boxes. for bible in bibles: if bible: @@ -481,7 +481,7 @@ book_data_temp.append(book) book_data = book_data_temp books = [book.name + u' ' for book in book_data] - books.sort(cmp=locale.strcoll) + books.sort(cmp=get_local_collator) add_widget_completer(books, self.quickSearchEdit) def onQuickVersionComboBox(self): === modified file 'openlp/plugins/custom/lib/mediaitem.py' --- openlp/plugins/custom/lib/mediaitem.py 2011-12-30 21:40:13 +0000 +++ openlp/plugins/custom/lib/mediaitem.py 2012-01-18 18:04:32 +0000 @@ -26,7 +26,6 @@ ############################################################################### import logging -import locale from PyQt4 import QtCore, QtGui from sqlalchemy.sql import or_, func @@ -34,6 +33,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_item_selected, translate from openlp.core.lib.ui import UiStrings +from oprnlp.core.utils import get_local_collator from openlp.plugins.custom.forms import EditCustomForm from openlp.plugins.custom.lib import CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide @@ -109,7 +109,7 @@ # Sort the customs by its title considering language specific # characters. lower() is needed for windows! custom_slides.sort( - cmp=locale.strcoll, key=lambda custom: custom.title.lower()) + cmp=get_local_collator, key=lambda custom: custom.title.lower()) for custom_slide in custom_slides: custom_name = QtGui.QListWidgetItem(custom_slide.title) custom_name.setData( === modified file 'openlp/plugins/images/lib/mediaitem.py' --- openlp/plugins/images/lib/mediaitem.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/images/lib/mediaitem.py 2012-01-18 18:04:32 +0000 @@ -27,7 +27,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -35,7 +34,8 @@ SettingsManager, translate, check_item_selected, check_directory_exists, \ Receiver, create_thumb, validate_thumb from openlp.core.lib.ui import UiStrings, critical_error_message_box -from openlp.core.utils import AppLocation, delete_file, get_images_filter +from openlp.core.utils import AppLocation, delete_file, get_images_filter, \ + get_local_collator log = logging.getLogger(__name__) @@ -120,7 +120,7 @@ self.plugin.formparent.displayProgressBar(len(images)) # Sort the themes by its filename considering language specific # characters. lower() is needed for windows! - images.sort(cmp=locale.strcoll, + images.sort(cmp=get_local_collator, key=lambda filename: os.path.split(unicode(filename))[1].lower()) for imageFile in images: if not initialLoad: === modified file 'openlp/plugins/media/lib/mediaitem.py' --- openlp/plugins/media/lib/mediaitem.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/media/lib/mediaitem.py 2012-01-18 18:04:32 +0000 @@ -27,7 +27,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -37,6 +36,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ media_item_combo_box from openlp.core.ui import Controller, Display +from openlp.core.utils import get_local_collator log = logging.getLogger(__name__) @@ -278,7 +278,7 @@ def loadList(self, media): # Sort the themes by its filename considering language specific # characters. lower() is needed for windows! - media.sort(cmp=locale.strcoll, + media.sort(cmp=get_local_collator, key=lambda filename: os.path.split(unicode(filename))[1].lower()) for track in media: track_info = QtCore.QFileInfo(track) @@ -298,7 +298,7 @@ def getList(self, type=MediaType.Audio): media = SettingsManager.load_list(self.settingsSection, u'media') - media.sort(cmp=locale.strcoll, + media.sort(cmp=get_local_collator, key=lambda filename: os.path.split(unicode(filename))[1].lower()) ext = [] if type == MediaType.Audio: === modified file 'openlp/plugins/presentations/lib/mediaitem.py' --- openlp/plugins/presentations/lib/mediaitem.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/presentations/lib/mediaitem.py 2012-01-18 18:04:32 +0000 @@ -27,7 +27,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -36,6 +35,7 @@ validate_thumb from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ media_item_combo_box +from openlp.core.utils import get_local_collator from openlp.plugins.presentations.lib import MessageListener log = logging.getLogger(__name__) @@ -168,7 +168,7 @@ self.plugin.formparent.displayProgressBar(len(files)) # Sort the themes by its filename considering language specific # characters. lower() is needed for windows! - files.sort(cmp=locale.strcoll, + files.sort(cmp=get_local_collator, key=lambda filename: os.path.split(unicode(filename))[1].lower()) for file in files: if not initialLoad: === modified file 'openlp/plugins/songs/forms/songexportform.py' --- openlp/plugins/songs/forms/songexportform.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/songs/forms/songexportform.py 2012-01-18 18:04:32 +0000 @@ -28,7 +28,6 @@ The :mod:`songexportform` module provides the wizard for exporting songs to the OpenLyrics format. """ -import locale import logging from PyQt4 import QtCore, QtGui @@ -36,6 +35,7 @@ from openlp.core.lib import build_icon, Receiver, SettingsManager, translate from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings +from openlp.core.utils import get_local_collator from openlp.plugins.songs.lib.db import Song from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport @@ -250,7 +250,7 @@ # Load the list of songs. Receiver.send_message(u'cursor_busy') songs = self.plugin.manager.get_all_objects(Song) - songs.sort(cmp=locale.strcoll, key=lambda song: song.title.lower()) + songs.sort(cmp=get_local_collator, key=lambda song: song.title.lower()) for song in songs: # No need to export temporary songs. if song.temporary: === modified file 'openlp/plugins/songs/lib/mediaitem.py' --- openlp/plugins/songs/lib/mediaitem.py 2011-12-30 21:40:13 +0000 +++ openlp/plugins/songs/lib/mediaitem.py 2012-01-18 18:04:32 +0000 @@ -26,7 +26,6 @@ ############################################################################### import logging -import locale import re import os import shutil @@ -38,7 +37,7 @@ translate, check_item_selected, PluginStatus from openlp.core.lib.ui import UiStrings, context_menu_action, \ context_menu_separator -from openlp.core.utils import AppLocation +from openlp.core.utils import AppLocation, get_local_collator from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ SongImportForm, SongExportForm from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \ @@ -240,7 +239,7 @@ # Sort the songs by its title considering language specific characters. # lower() is needed for windows! searchresults.sort( - cmp=locale.strcoll, key=lambda song: song.title.lower()) + cmp=get_local_collator, key=lambda song: song.title.lower()) for song in searchresults: # Do not display temporary songs if song.temporary: === modified file 'scripts/check_dependencies.py' --- scripts/check_dependencies.py 2011-10-26 07:40:12 +0000 +++ scripts/check_dependencies.py 2012-01-18 18:04:32 +0000 @@ -74,6 +74,7 @@ 'mako', 'migrate', 'uno', + 'icu', ]
_______________________________________________ Mailing list: https://launchpad.net/~openlp-core Post to : openlp-core@lists.launchpad.net Unsubscribe : https://launchpad.net/~openlp-core More help : https://help.launchpad.net/ListHelp