From 0836306f1bd3b03ab3e4b48805dcbe16aa998781 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 12 Oct 2012 00:55:21 +0200 Subject: [PATCH 1/5] Bug 687638: add function locale_compare. --- openlp/core/utils/__init__.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 41a097a15..957fde829 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -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 QLocale 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. + """ + # 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'] From 7b608a948ad473b9f514dc10cc6a85f40b6a6683 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 12 Oct 2012 02:03:37 +0200 Subject: [PATCH 2/5] Bug 687638: use locale aware comparison for song list. --- openlp/plugins/songs/lib/mediaitem.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 88999dce4..e338a11d9 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -27,7 +27,6 @@ ############################################################################### import logging -import locale import re import os import shutil @@ -40,7 +39,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_directory_exists from openlp.core.lib.ui import UiStrings, create_widget_action from openlp.core.lib.settings import Settings -from openlp.core.utils import AppLocation +from openlp.core.utils import AppLocation, locale_compare from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ SongImportForm, SongExportForm from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \ @@ -263,7 +262,7 @@ class SongMediaItem(MediaManagerItem): # 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=locale_compare, key=lambda song: song.title) for song in searchresults: # Do not display temporary songs if song.temporary: From 2cc18a8fb448f62adc1be25270141bff00475b33 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 12 Oct 2012 13:55:06 +0200 Subject: [PATCH 3/5] Bug #687638: use locale aware comparison for songs by default. --- openlp/core/utils/__init__.py | 4 ++-- openlp/plugins/songs/forms/songexportform.py | 3 +-- openlp/plugins/songs/lib/db.py | 10 +++++++++- openlp/plugins/songs/lib/mediaitem.py | 7 ++----- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 957fde829..764cab06a 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -490,11 +490,11 @@ def format_time(text, local_time): def locale_compare(string1, string2): """ - Compares two strings according to the current QLocale settings. + 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. + 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. diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py index c483c91b6..15239f9c2 100644 --- a/openlp/plugins/songs/forms/songexportform.py +++ b/openlp/plugins/songs/forms/songexportform.py @@ -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: diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index d79d177fd..0d404a235 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -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): diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index e338a11d9..0808bcba0 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -39,7 +39,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_directory_exists from openlp.core.lib.ui import UiStrings, create_widget_action from openlp.core.lib.settings import Settings -from openlp.core.utils import AppLocation, locale_compare +from openlp.core.utils import AppLocation from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ SongImportForm, SongExportForm from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \ @@ -259,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_compare, key=lambda song: song.title) + searchresults.sort() for song in searchresults: # Do not display temporary songs if song.temporary: From 4427d4168ed2bb2a08b322f97ab81f8f7d06fdf4 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 12 Oct 2012 15:00:56 +0200 Subject: [PATCH 4/5] Bug #687638: use locale aware comparison in other places too. --- openlp/core/ui/thememanager.py | 9 ++++----- openlp/plugins/bibles/forms/bibleimportform.py | 5 ++--- openlp/plugins/bibles/lib/mediaitem.py | 6 +++--- openlp/plugins/custom/lib/db.py | 11 ++++++++++- openlp/plugins/custom/lib/mediaitem.py | 6 +++--- openlp/plugins/images/lib/mediaitem.py | 12 ++++++------ openlp/plugins/media/lib/mediaitem.py | 14 +++++++------- openlp/plugins/presentations/lib/mediaitem.py | 10 +++++----- openlp/plugins/songs/lib/db.py | 2 +- 9 files changed, 41 insertions(+), 34 deletions(-) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 844ffec8c..a5293e3a8 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -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 diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index 0a1d4cc23..d805ba34f 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -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): diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 5176e7d47..0647076c8 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -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): diff --git a/openlp/plugins/custom/lib/db.py b/openlp/plugins/custom/lib/db.py index 6f3155f48..c885562f2 100644 --- a/openlp/plugins/custom/lib/db.py +++ b/openlp/plugins/custom/lib/db.py @@ -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): """ diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 663c5489d..01053549f 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -27,7 +27,6 @@ ############################################################################### import logging -import locale from PyQt4 import QtCore, QtGui from sqlalchemy.sql import or_, func @@ -36,6 +35,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_item_selected, translate from openlp.core.lib.ui import UiStrings from openlp.core.lib.settings import Settings +from openlp.core.utils import locale_compare from openlp.plugins.custom.forms import EditCustomForm from openlp.plugins.custom.lib import CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide @@ -110,9 +110,9 @@ class CustomMediaItem(MediaManagerItem): self.saveAutoSelectId() self.listView.clear() # Sort the customs by its title considering language specific - # characters. lower() is needed for windows! + # characters. custom_slides.sort( - cmp=locale.strcoll, key=lambda custom: custom.title.lower()) + cmp=locale_compare, key=lambda custom: custom.title) for custom_slide in custom_slides: custom_name = QtGui.QListWidgetItem(custom_slide.title) custom_name.setData( diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 0fdb1537c..9239f8d72 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -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) diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index bd987e79d..9f661149b 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -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 diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 290882e26..9cfed177c 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -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() diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index 0d404a235..36b6d53ad 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -69,7 +69,7 @@ class Song(BaseModel): 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) From e26cd9ca6bc63b31cbe75b5660f81a8b52cd538a Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 12 Oct 2012 21:40:15 +0200 Subject: [PATCH 5/5] Bug #687638: for customs cmp method in sort not necessary. --- openlp/plugins/custom/lib/mediaitem.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 01053549f..10a3ec056 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -35,7 +35,6 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_item_selected, translate from openlp.core.lib.ui import UiStrings from openlp.core.lib.settings import Settings -from openlp.core.utils import locale_compare from openlp.plugins.custom.forms import EditCustomForm from openlp.plugins.custom.lib import CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide @@ -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. - custom_slides.sort( - cmp=locale_compare, key=lambda custom: custom.title) + custom_slides.sort() for custom_slide in custom_slides: custom_name = QtGui.QListWidgetItem(custom_slide.title) custom_name.setData(