matysek has proposed merging lp:~mzibricky/openlp/bug-687638 into lp:openlp.
Requested reviews: Raoul Snyman (raoul-snyman) Tim Bentley (trb143) For more details, see: https://code.launchpad.net/~mzibricky/openlp/bug-687638/+merge/129501 This should fix the locale aware sorting of songs and other items. The implementation uses Qt function QString.localeAwareCompare() for that. Some inspiration is based on branch ~m2j/openlp/bug-687638. I tested it mostly on osx. I probably need to test it on windows with a build. -- https://code.launchpad.net/~mzibricky/openlp/bug-687638/+merge/129501 Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/ui/thememanager.py' --- openlp/core/ui/thememanager.py 2012-09-19 18:43:02 +0000 +++ openlp/core/ui/thememanager.py 2012-10-12 19:42:25 +0000 @@ -30,7 +30,6 @@ import zipfile import shutil import logging -import locale import re from xml.etree.ElementTree import ElementTree, XML @@ -46,7 +45,8 @@ create_widget_action 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, locale_compare, \ + get_filesystem_encoding log = logging.getLogger(__name__) @@ -457,9 +457,8 @@ self.configUpdated() files = SettingsManager.get_files(self.settingsSection, u'.png') # Sort the themes by its name considering language specific characters. - # lower() is needed for windows! - files.sort(key=lambda file_name: unicode(file_name).lower(), - cmp=locale.strcoll) + files.sort(key=lambda file_name: unicode(file_name), + cmp=locale_compare) # 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 2012-09-17 22:20:38 +0000 +++ openlp/core/utils/__init__.py 2012-10-12 19:42:25 +0000 @@ -488,10 +488,24 @@ return re.sub('\%[a-zA-Z]', match_formatting, text) +def locale_compare(string1, string2): + """ + Compares two strings according to the current locale settings. + + As any other compare function, returns a negative, or a positive value, + or 0, depending on whether string1 collates before or after string2 or + is equal to it. Comparison is case insensitive. + """ + # Function locale.strcol() from standard Python library does not work + # properly on Windows and probably somewhere else. + return int(QtCore.QString.localeAwareCompare( + QtCore.QString(string1).toLower(), QtCore.QString(string2).toLower())) + + 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'format_time'] + u'delete_file', u'clean_filename', u'format_time', u'locale_compare'] === modified file 'openlp/plugins/bibles/forms/bibleimportform.py' --- openlp/plugins/bibles/forms/bibleimportform.py 2012-06-22 14:14:53 +0000 +++ openlp/plugins/bibles/forms/bibleimportform.py 2012-10-12 19:42:25 +0000 @@ -30,7 +30,6 @@ """ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -39,7 +38,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.settings import Settings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings -from openlp.core.utils import AppLocation +from openlp.core.utils import AppLocation, locale_compare from openlp.plugins.bibles.lib.manager import BibleFormat from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename @@ -523,7 +522,7 @@ """ self.webTranslationComboBox.clear() bibles = self.web_bible_list[index].keys() - bibles.sort(cmp=locale.strcoll) + bibles.sort(cmp=locale_compare) self.webTranslationComboBox.addItems(bibles) def onOsisBrowseButtonClicked(self): === modified file 'openlp/plugins/bibles/lib/mediaitem.py' --- openlp/plugins/bibles/lib/mediaitem.py 2012-07-10 04:56:07 +0000 +++ openlp/plugins/bibles/lib/mediaitem.py 2012-10-12 19:42:25 +0000 @@ -27,7 +27,6 @@ ############################################################################### import logging -import locale from PyQt4 import QtCore, QtGui @@ -38,6 +37,7 @@ from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \ create_horizontal_adjusting_combo_box, critical_error_message_box, \ find_and_set_in_combo_box, build_icon +from openlp.core.utils import locale_compare from openlp.plugins.bibles.forms import BibleImportForm, EditBibleForm from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \ VerseReferenceList, get_reference_separator, LanguageSelection, \ @@ -381,7 +381,7 @@ # Get all bibles and sort the list. bibles = self.plugin.manager.get_bibles().keys() bibles = filter(None, bibles) - bibles.sort(cmp=locale.strcoll) + bibles.sort(cmp=locale_compare) # Load the bibles into the combo boxes. self.quickVersionComboBox.addItems(bibles) self.quickSecondComboBox.addItems(bibles) @@ -538,7 +538,7 @@ data = BiblesResourcesDB.get_book_by_id( book.book_reference_id) books.append(data[u'name'] + u' ') - books.sort(cmp=locale.strcoll) + books.sort(cmp=locale_compare) set_case_insensitive_completer(books, self.quickSearchEdit) def onImportClick(self): === modified file 'openlp/plugins/custom/lib/db.py' --- openlp/plugins/custom/lib/db.py 2012-06-22 14:14:53 +0000 +++ openlp/plugins/custom/lib/db.py 2012-10-12 19:42:25 +0000 @@ -34,12 +34,21 @@ from sqlalchemy.orm import mapper from openlp.core.lib.db import BaseModel, init_db +from openlp.core.utils import locale_compare class CustomSlide(BaseModel): """ CustomSlide model """ - pass + # By default sort the customs by its title considering language specific + # characters. + def __lt__(self, other): + r = locale_compare(self.title, other.title) + return True if r < 0 else False + + def __eq__(self, other): + return 0 == locale_compare(self.title, other.title) + def init_schema(url): """ === modified file 'openlp/plugins/custom/lib/mediaitem.py' --- openlp/plugins/custom/lib/mediaitem.py 2012-06-22 14:14:53 +0000 +++ openlp/plugins/custom/lib/mediaitem.py 2012-10-12 19:42:25 +0000 @@ -27,7 +27,6 @@ ############################################################################### import logging -import locale from PyQt4 import QtCore, QtGui from sqlalchemy.sql import or_, func @@ -109,10 +108,7 @@ # Sort out what custom we want to select after loading the list. self.saveAutoSelectId() self.listView.clear() - # 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()) + custom_slides.sort() 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 2012-06-30 15:19:33 +0000 +++ openlp/plugins/images/lib/mediaitem.py 2012-10-12 19:42:25 +0000 @@ -28,7 +28,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -37,7 +36,8 @@ Receiver, create_thumb, validate_thumb from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.settings import Settings -from openlp.core.utils import AppLocation, delete_file, get_images_filter +from openlp.core.utils import AppLocation, delete_file, locale_compare, \ + get_images_filter log = logging.getLogger(__name__) @@ -126,10 +126,10 @@ if not initialLoad: Receiver.send_message(u'cursor_busy') 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, - key=lambda filename: os.path.split(unicode(filename))[1].lower()) + # Sort the images by its filename considering language specific + # characters. + images.sort(cmp=locale_compare, + key=lambda filename: os.path.split(unicode(filename))[1]) for imageFile in images: filename = os.path.split(unicode(imageFile))[1] thumb = os.path.join(self.servicePath, filename) === modified file 'openlp/plugins/media/lib/mediaitem.py' --- openlp/plugins/media/lib/mediaitem.py 2012-10-09 18:00:33 +0000 +++ openlp/plugins/media/lib/mediaitem.py 2012-10-12 19:42:25 +0000 @@ -28,7 +28,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -39,6 +38,7 @@ create_horizontal_adjusting_combo_box from openlp.core.ui import Controller, Display from openlp.core.ui.media import get_media_players, set_media_players +from openlp.core.utils import locale_compare log = logging.getLogger(__name__) @@ -285,10 +285,10 @@ u'media', self.getFileList()) def loadList(self, media): - # Sort the themes by its filename considering language specific - # characters. lower() is needed for windows! - media.sort(cmp=locale.strcoll, - key=lambda filename: os.path.split(unicode(filename))[1].lower()) + # Sort the media by its filename considering language specific + # characters. + media.sort(cmp=locale_compare, + key=lambda filename: os.path.split(unicode(filename))[1]) for track in media: track_info = QtCore.QFileInfo(track) if track_info.isFile(): @@ -307,8 +307,8 @@ def getList(self, type=MediaType.Audio): media = SettingsManager.load_list(self.settingsSection, u'media') - media.sort(cmp=locale.strcoll, - key=lambda filename: os.path.split(unicode(filename))[1].lower()) + media.sort(cmp=locale_compare, + key=lambda filename: os.path.split(unicode(filename))[1]) ext = [] if type == MediaType.Audio: ext = self.plugin.audio_extensions_list === modified file 'openlp/plugins/presentations/lib/mediaitem.py' --- openlp/plugins/presentations/lib/mediaitem.py 2012-06-22 14:14:53 +0000 +++ openlp/plugins/presentations/lib/mediaitem.py 2012-10-12 19:42:25 +0000 @@ -28,7 +28,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -38,6 +37,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ create_horizontal_adjusting_combo_box from openlp.core.lib.settings import Settings +from openlp.core.utils import locale_compare from openlp.plugins.presentations.lib import MessageListener log = logging.getLogger(__name__) @@ -169,10 +169,10 @@ if not initialLoad: Receiver.send_message(u'cursor_busy') 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, - key=lambda filename: os.path.split(unicode(filename))[1].lower()) + # Sort the presentations by its filename considering language specific + # characters. + files.sort(cmp=locale_compare, + key=lambda filename: os.path.split(unicode(filename))[1]) for file in files: if not initialLoad: self.plugin.formParent.incrementProgressBar() === modified file 'openlp/plugins/songs/forms/songexportform.py' --- openlp/plugins/songs/forms/songexportform.py 2012-06-22 14:14:53 +0000 +++ openlp/plugins/songs/forms/songexportform.py 2012-10-12 19:42:25 +0000 @@ -29,7 +29,6 @@ The :mod:`songexportform` module provides the wizard for exporting songs to the OpenLyrics format. """ -import locale import logging from PyQt4 import QtCore, QtGui @@ -252,7 +251,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() for song in songs: # No need to export temporary songs. if song.temporary: === modified file 'openlp/plugins/songs/lib/db.py' --- openlp/plugins/songs/lib/db.py 2012-06-22 14:14:53 +0000 +++ openlp/plugins/songs/lib/db.py 2012-10-12 19:42:25 +0000 @@ -35,6 +35,7 @@ from sqlalchemy.sql.expression import func from openlp.core.lib.db import BaseModel, init_db +from openlp.core.utils import locale_compare class Author(BaseModel): """ @@ -63,7 +64,14 @@ """ Song model """ - pass + # By default sort the songs by its title considering language specific + # characters. + def __lt__(self, other): + r = locale_compare(self.title, other.title) + return True if r < 0 else False + + def __eq__(self, other): + return 0 == locale_compare(self.title, other.title) class Topic(BaseModel): === modified file 'openlp/plugins/songs/lib/mediaitem.py' --- openlp/plugins/songs/lib/mediaitem.py 2012-07-07 14:54:14 +0000 +++ openlp/plugins/songs/lib/mediaitem.py 2012-10-12 19:42:25 +0000 @@ -27,7 +27,6 @@ ############################################################################### import logging -import locale import re import os import shutil @@ -260,10 +259,7 @@ log.debug(u'display results Song') self.saveAutoSelectId() self.listView.clear() - # 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()) + searchresults.sort() for song in searchresults: # Do not display temporary songs if song.temporary:
_______________________________________________ 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