In a song, replace apostrophes with an empty string instead of a space. This allows the searcher to find words containing "it's" and "Lord's" should they type "its" or "Lords" (and vice versa).

Also reinstate the setting of search_lyrics by clean_song.

bzr-revno: 1612
This commit is contained in:
Jonathan Corwin 2011-06-04 17:07:42 +01:00
commit 9230fbb116
3 changed files with 30 additions and 15 deletions

View File

@ -92,7 +92,7 @@ class MediaManagerItem(QtGui.QWidget):
""" """
QtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
self.hide() self.hide()
self.whitespace = re.compile(r'\W+', re.UNICODE) self.whitespace = re.compile(r'[\W_]+', re.UNICODE)
self.plugin = plugin self.plugin = plugin
visible_title = self.plugin.getString(StringContent.VisibleName) visible_title = self.plugin.getString(StringContent.VisibleName)
self.title = unicode(visible_title[u'title']) self.title = unicode(visible_title[u'title'])

View File

@ -32,6 +32,9 @@ from openlp.core.lib import translate
from db import Author from db import Author
from ui import SongStrings from ui import SongStrings
WHITESPACE = re.compile(r'[\W_]+', re.UNICODE)
APOSTROPHE = re.compile(u'[\'`ʻ]', re.UNICODE)
class VerseType(object): class VerseType(object):
""" """
VerseType provides an enumeration for the tags that may be associated VerseType provides an enumeration for the tags that may be associated
@ -246,6 +249,12 @@ def retrieve_windows_encoding(recommendation=None):
return None return None
return filter(lambda item: item[1] == choice[0], encodings)[0][0] return filter(lambda item: item[1] == choice[0], encodings)[0][0]
def clean_string(string):
"""
Strips punctuation from the passed string to assist searching
"""
return WHITESPACE.sub(u' ', APOSTROPHE.sub(u'', string)).lower()
def clean_song(manager, song): def clean_song(manager, song):
""" """
Cleans the search title, rebuilds the search lyrics, adds a default author Cleans the search title, rebuilds the search lyrics, adds a default author
@ -262,9 +271,8 @@ def clean_song(manager, song):
if song.alternate_title is None: if song.alternate_title is None:
song.alternate_title = u'' song.alternate_title = u''
song.alternate_title = song.alternate_title.strip() song.alternate_title = song.alternate_title.strip()
whitespace = re.compile(r'\W+', re.UNICODE) song.search_title = clean_string(song.title) + u'@' + \
song.search_title = (whitespace.sub(u' ', song.title).strip() + u'@' + clean_string(song.alternate_title)
whitespace.sub(u' ', song.alternate_title).strip()).strip().lower()
# Only do this, if we the song is a 1.9.4 song (or older). # Only do this, if we the song is a 1.9.4 song (or older).
if song.lyrics.find(u'<lyrics language="en">') != -1: if song.lyrics.find(u'<lyrics language="en">') != -1:
# Remove the old "language" attribute from lyrics tag (prior to 1.9.5). # Remove the old "language" attribute from lyrics tag (prior to 1.9.5).
@ -273,8 +281,8 @@ def clean_song(manager, song):
song.lyrics = song.lyrics.replace( song.lyrics = song.lyrics.replace(
u'<lyrics language="en">', u'<lyrics>') u'<lyrics language="en">', u'<lyrics>')
verses = SongXML().get_verses(song.lyrics) verses = SongXML().get_verses(song.lyrics)
lyrics = u' '.join([whitespace.sub(u' ', verse[1]) for verse in verses]) song.search_lyrics = u' '.join([clean_string(verse[1])
song.search_lyrics = lyrics.lower() for verse in verses])
# We need a new and clean SongXML instance. # We need a new and clean SongXML instance.
sxml = SongXML() sxml = SongXML()
# Rebuild the song's verses, to remove any wrong verse names (for # Rebuild the song's verses, to remove any wrong verse names (for
@ -316,6 +324,11 @@ def clean_song(manager, song):
if order not in compare_order: if order not in compare_order:
song.verse_order = u'' song.verse_order = u''
break break
else:
verses = SongXML().get_verses(song.lyrics)
song.search_lyrics = u' '.join([clean_string(verse[1])
for verse in verses])
# The song does not have any author, add one. # The song does not have any author, add one.
if not song.authors: if not song.authors:
name = SongStrings.AuthorUnknown name = SongStrings.AuthorUnknown

View File

@ -38,7 +38,8 @@ from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
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, \
clean_string
from openlp.plugins.songs.lib.db import Author, Song from openlp.plugins.songs.lib.db import Author, Song
from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib.ui import SongStrings
@ -181,13 +182,14 @@ class SongMediaItem(MediaManagerItem):
elif search_type == SongSearch.Titles: elif search_type == SongSearch.Titles:
log.debug(u'Titles Search') log.debug(u'Titles Search')
search_results = self.plugin.manager.get_all_objects(Song, search_results = self.plugin.manager.get_all_objects(Song,
Song.search_title.like(u'%' + self.whitespace.sub(u' ', Song.search_title.like(u'%' + clean_string(search_keywords) +
search_keywords.lower()) + u'%')) u'%'))
self.displayResultsSong(search_results) self.displayResultsSong(search_results)
elif search_type == SongSearch.Lyrics: elif search_type == SongSearch.Lyrics:
log.debug(u'Lyrics Search') log.debug(u'Lyrics Search')
search_results = self.plugin.manager.get_all_objects(Song, search_results = self.plugin.manager.get_all_objects(Song,
Song.search_lyrics.like(u'%' + search_keywords.lower() + u'%')) Song.search_lyrics.like(u'%' + clean_string(search_keywords) +
u'%'))
self.displayResultsSong(search_results) self.displayResultsSong(search_results)
elif search_type == SongSearch.Authors: elif search_type == SongSearch.Authors:
log.debug(u'Authors Search') log.debug(u'Authors Search')
@ -198,16 +200,16 @@ class SongMediaItem(MediaManagerItem):
elif search_type == SongSearch.Themes: elif search_type == SongSearch.Themes:
log.debug(u'Theme Search') log.debug(u'Theme Search')
search_results = self.plugin.manager.get_all_objects(Song, search_results = self.plugin.manager.get_all_objects(Song,
Song.theme_name.like(u'%' + self.whitespace.sub(u' ', Song.theme_name.like(u'%' + search_keywords + u'%'))
search_keywords) + u'%'))
self.displayResultsSong(search_results) self.displayResultsSong(search_results)
self.check_search_result() self.check_search_result()
def searchEntire(self, search_keywords): def searchEntire(self, search_keywords):
return self.plugin.manager.get_all_objects(Song, return self.plugin.manager.get_all_objects(Song,
or_(Song.search_title.like(u'%' + self.whitespace.sub(u' ', or_(Song.search_title.like(u'%' + clean_string(search_keywords)
search_keywords.lower()) + u'%'), + u'%'),
Song.search_lyrics.like(u'%' + search_keywords.lower() + u'%'), Song.search_lyrics.like(u'%' + clean_string(search_keywords)
+ u'%'),
Song.comments.like(u'%' + search_keywords.lower() + u'%'))) Song.comments.like(u'%' + search_keywords.lower() + u'%')))
def onSongListLoad(self): def onSongListLoad(self):