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 # Function locale.strcol() from standard Python library does not work
# properly on Windows and probably somewhere else. # properly on Windows and probably somewhere else.
return int(QtCore.QString.localeAwareCompare( return QtCore.QString.localeAwareCompare(string1.lower(), string2.lower())
QtCore.QString(string1).toLower(), QtCore.QString(string2).toLower()))
# 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 from languagemanager import LanguageManager
@ -508,4 +513,5 @@ from actions import ActionList
__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version', __all__ = [u'AppLocation', u'get_application_version', u'check_latest_version',
u'add_actions', u'get_filesystem_encoding', u'LanguageManager', u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance', 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 create_separated_list
from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings 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.db import Song
from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport
@ -251,7 +252,8 @@ class SongExportForm(OpenLPWizard):
# Load the list of songs. # Load the list of songs.
Receiver.send_message(u'cursor_busy') Receiver.send_message(u'cursor_busy')
songs = self.plugin.manager.get_all_objects(Song) 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: for song in songs:
# No need to export temporary songs. # No need to export temporary songs.
if song.temporary: if song.temporary:

View File

@ -31,11 +31,11 @@ the Songs plugin
""" """
from sqlalchemy import Column, ForeignKey, Table, types 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 sqlalchemy.sql.expression import func
from PyQt4 import QtCore
from openlp.core.lib.db import BaseModel, init_db from openlp.core.lib.db import BaseModel, init_db
from openlp.core.utils import locale_compare
class Author(BaseModel): class Author(BaseModel):
""" """
@ -64,14 +64,22 @@ class Song(BaseModel):
""" """
Song model Song model
""" """
# By default sort the songs by its title considering language specific def __init__(self):
# characters. self.sort_string = ''
def __lt__(self, other):
r = locale_compare(self.title, other.title)
return True if r < 0 else False
def __eq__(self, other): # This decorator tells sqlalchemy to call this method everytime
return 0 == locale_compare(self.title, other.title) # 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): class Topic(BaseModel):

View File

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