This should fix the locale aware sorting of songs and other items. The implementation uses Qt function QString.localeAwareCompare() for that.

bzr-revno: 2086
Fixes: https://launchpad.net/bugs/687638
This commit is contained in:
Martin Zibricky 2012-10-13 19:08:33 +02:00 committed by Raoul Snyman
commit 5c8c5cafaa
12 changed files with 64 additions and 44 deletions

View File

@ -30,7 +30,6 @@ import os
import zipfile
import shutil
import logging
import locale
import re
from xml.etree.ElementTree import ElementTree, XML
@ -46,7 +45,8 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
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 @@ class ThemeManager(QtGui.QWidget):
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

View File

@ -488,10 +488,24 @@ def format_time(text, local_time):
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']

View File

@ -30,7 +30,6 @@ The bible import functions for OpenLP
"""
import logging
import os
import locale
from PyQt4 import QtCore, QtGui
@ -39,7 +38,7 @@ from openlp.core.lib.db import delete_database
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 @@ class BibleImportForm(OpenLPWizard):
"""
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):

View File

@ -27,7 +27,6 @@
###############################################################################
import logging
import locale
from PyQt4 import QtCore, QtGui
@ -38,6 +37,7 @@ from openlp.core.lib.settings import Settings
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 @@ class BibleMediaItem(MediaManagerItem):
# 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 @@ class BibleMediaItem(MediaManagerItem):
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):

View File

@ -34,12 +34,21 @@ from sqlalchemy import Column, Table, types
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):
"""

View File

@ -27,7 +27,6 @@
###############################################################################
import logging
import locale
from PyQt4 import QtCore, QtGui
from sqlalchemy.sql import or_, func
@ -109,10 +108,7 @@ class CustomMediaItem(MediaManagerItem):
# 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(

View File

@ -28,7 +28,6 @@
import logging
import os
import locale
from PyQt4 import QtCore, QtGui
@ -37,7 +36,8 @@ from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
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 @@ class ImageMediaItem(MediaManagerItem):
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)

View File

@ -28,7 +28,6 @@
import logging
import os
import locale
from PyQt4 import QtCore, QtGui
@ -39,6 +38,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
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 @@ class MediaMediaItem(MediaManagerItem):
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 @@ class MediaMediaItem(MediaManagerItem):
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

View File

@ -28,7 +28,6 @@
import logging
import os
import locale
from PyQt4 import QtCore, QtGui
@ -38,6 +37,7 @@ from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \
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 @@ class PresentationMediaItem(MediaManagerItem):
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()

View File

@ -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 @@ class SongExportForm(OpenLPWizard):
# 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:

View File

@ -35,6 +35,7 @@ from sqlalchemy.orm import mapper, relation
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 @@ class Song(BaseModel):
"""
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):

View File

@ -27,7 +27,6 @@
###############################################################################
import logging
import locale
import re
import os
import shutil
@ -260,10 +259,7 @@ class SongMediaItem(MediaManagerItem):
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: