Precompute the whole comparision key for song sorting.

This commit is contained in:
M2j 2013-03-31 12:31:54 +02:00
parent 76ea812629
commit 118f295204
4 changed files with 18 additions and 46 deletions

View File

@ -398,25 +398,18 @@ def get_local_key(string):
def get_natural_key(string):
"""
Generate a key for locale aware natural string sorting. Returns a list of strings and integers.
``string``
A string, list or tuple which represents the item string.
Generate a key for locale aware natural string sorting.
Returns a list of string compare keys and integers.
"""
if isinstance(string, basestring):
string = re.findall(r'(\d+|\D+)', string)
if len(string) == 1:
return list(get_local_key(string[0]))
elif isinstance(string, tuple):
string = list(string)
if isinstance(string, list):
for index, part in enumerate(string):
if isinstance(part, basestring):
if part.isdigit():
string[index] = int(part)
else:
string[index] = get_local_key(part)
return string
key = re.findall(r'(\d+|\D+)', string)
if len(key) == 1:
return list(get_local_key(string))
for index, part in enumerate(key):
if part.isdigit():
key[index] = int(part)
else:
key[index] = get_local_key(part)
return key
from applocation import AppLocation

View File

@ -37,7 +37,6 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Registry, UiStrings, create_separated_list, build_icon, translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
from openlp.core.utils import get_natural_key
from openlp.plugins.songs.lib.db import Song
from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport
@ -222,7 +221,7 @@ class SongExportForm(OpenLPWizard):
# Load the list of songs.
self.application.set_busy_cursor()
songs = self.plugin.manager.get_all_objects(Song)
songs.sort(key=lambda song: get_natural_key(song.sort_key))
songs.sort(key=lambda song: song.sort_key)
for song in songs:
# No need to export temporary songs.
if song.temporary:

View File

@ -38,6 +38,7 @@ from sqlalchemy.orm import mapper, relation, reconstructor
from sqlalchemy.sql.expression import func
from openlp.core.lib.db import BaseModel, init_db
from openlp.core.utils import get_natural_key
class Author(BaseModel):
@ -69,36 +70,15 @@ class Song(BaseModel):
def __init__(self):
self.sort_key = ()
def _try_int(self, s):
"""
Convert to integer if possible.
"""
try:
return int(s)
except:
return s.lower()
def _natsort_key(self, s):
"""
Used internally to get a tuple by which s is sorted.
"""
return map(self._try_int, re.findall(r'(\d+|\D+)', s))
# This decorator tells sqlalchemy to call this method everytime
# any data on this object is updated.
@reconstructor
def init_on_load(self):
"""
Precompute a tuple to be used for sorting.
Precompute a natural sorting, locale aware sorting key.
Song sorting is performance sensitive operation.
To get maximum speed lets precompute the string
used for comparison.
To get maximum speed lets precompute the sorting key.
"""
# Avoid the overhead of converting string to lowercase and to QString
# with every call to sort().
self.sort_key = self._natsort_key(self.title)
self.sort_key = get_natural_key(self.title)
class Topic(BaseModel):

View File

@ -38,7 +38,7 @@ from sqlalchemy.sql import or_
from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, PluginStatus, ServiceItemContext, Settings, \
UiStrings, translate, check_item_selected, create_separated_list, check_directory_exists
from openlp.core.lib.ui import create_widget_action
from openlp.core.utils import AppLocation, get_natural_key
from openlp.core.utils import AppLocation
from openlp.plugins.songs.forms.editsongform import EditSongForm
from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm
from openlp.plugins.songs.forms.songimportform import SongImportForm
@ -225,7 +225,7 @@ class SongMediaItem(MediaManagerItem):
log.debug(u'display results Song')
self.save_auto_select_id()
self.list_view.clear()
searchresults.sort(key=lambda song: get_natural_key(song.sort_key))
searchresults.sort(key=lambda song: song.sort_key)
for song in searchresults:
# Do not display temporary songs
if song.temporary: