Performance improvements in sort from Databases.

Language aware.

bzr-revno: 2090
Fixes: https://launchpad.net/bugs/687638
This commit is contained in:
Martin Zibricky 2012-10-15 05:51:22 +01:00 committed by Tim Bentley
commit 2f53897df5
4 changed files with 32 additions and 15 deletions

View File

@ -498,8 +498,13 @@ def locale_compare(string1, string2):
"""
# 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()))
return QtCore.QString.localeAwareCompare(string1.lower(), string2.lower())
# For performance reasons provide direct reference to compare function
# without wrapping it in another function making te string lowercase.
# This is needed for sorting songs.
locale_direct_compare = QtCore.QString.localeAwareCompare
from languagemanager import LanguageManager
@ -508,4 +513,5 @@ 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'locale_compare']
u'delete_file', u'clean_filename', u'format_time', u'locale_compare',
u'locale_direct_compare']

View File

@ -37,6 +37,7 @@ from openlp.core.lib import build_icon, Receiver, SettingsManager, translate, \
create_separated_list
from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
from openlp.core.utils import locale_direct_compare
from openlp.plugins.songs.lib.db import Song
from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport
@ -251,7 +252,8 @@ class SongExportForm(OpenLPWizard):
# Load the list of songs.
Receiver.send_message(u'cursor_busy')
songs = self.plugin.manager.get_all_objects(Song)
songs.sort()
songs.sort(
cmp=locale_direct_compare, key=lambda song: song.sort_string)
for song in songs:
# No need to export temporary songs.
if song.temporary:

View File

@ -31,11 +31,11 @@ the Songs plugin
"""
from sqlalchemy import Column, ForeignKey, Table, types
from sqlalchemy.orm import mapper, relation
from sqlalchemy.orm import mapper, relation, reconstructor
from sqlalchemy.sql.expression import func
from PyQt4 import QtCore
from openlp.core.lib.db import BaseModel, init_db
from openlp.core.utils import locale_compare
class Author(BaseModel):
"""
@ -64,14 +64,22 @@ class Song(BaseModel):
"""
Song model
"""
# 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 __init__(self):
self.sort_string = ''
def __eq__(self, other):
return 0 == locale_compare(self.title, other.title)
# This decorator tells sqlalchemy to call this method everytime
# any data on this object are updated.
@reconstructor
def init_on_load(self):
"""
Precompute string to be used for sorting.
Song sorting is performance sensitive operation.
To get maximum speed lets precompute the string
used for comparison.
"""
# Avoid the overhead of converting string to lowercase and to QString
self.sort_string = QtCore.QString(self.title.lower())
class Topic(BaseModel):

View File

@ -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
from openlp.core.utils import AppLocation, locale_direct_compare
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
SongImportForm, SongExportForm
from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \
@ -259,7 +259,8 @@ class SongMediaItem(MediaManagerItem):
log.debug(u'display results Song')
self.saveAutoSelectId()
self.listView.clear()
searchresults.sort()
searchresults.sort(
cmp=locale_direct_compare, key=lambda song: song.sort_string)
for song in searchresults:
# Do not display temporary songs
if song.temporary: