← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~martin-hosken/openlp/subsearch into lp:openlp

 

mhosken has proposed merging lp:~martin-hosken/openlp/subsearch into lp:openlp.

Requested reviews:
  Andreas Preikschat (googol)

For more details, see:
https://code.launchpad.net/~martin-hosken/openlp/subsearch/+merge/152404

This adds a feature whereby a user can constrain their search of songs in the song database to those already in the search results list. This allows for a user to slowly refine their search, homing in on what they want to find. It is a feature I have often desired while preparing services and trying to track down the perfect song ;)

As pre request, this refactoring moves the code up to be shared by songs and custom plugins.
-- 
https://code.launchpad.net/~martin-hosken/openlp/subsearch/+merge/152404
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/.version'
--- openlp/.version	2013-01-08 20:44:56 +0000
+++ openlp/.version	2013-03-08 13:50:34 +0000
@@ -1,1 +1,1 @@
-2.1.0-bzr2141
+2.1.0-bzr2202
\ No newline at end of file

=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py	2013-02-19 09:56:36 +0000
+++ openlp/core/lib/mediamanageritem.py	2013-03-08 13:50:34 +0000
@@ -288,6 +288,9 @@
         self.searchLayout.addLayout(self.searchTextLayout)
         self.searchButtonLayout = QtGui.QHBoxLayout()
         self.searchButtonLayout.setObjectName(u'searchButtonLayout')
+        self.searchLimitCheck = QtGui.QCheckBox()
+        self.searchLimitCheck.setObjectName(u'searchLimitCheck')
+        self.searchButtonLayout.addWidget(self.searchLimitCheck)
         self.searchButtonLayout.addStretch()
         self.searchTextButton = QtGui.QPushButton(self.searchWidget)
         self.searchTextButton.setObjectName(u'searchTextButton')

=== modified file 'openlp/core/lib/uistrings.py'
--- openlp/core/lib/uistrings.py	2013-02-01 19:58:18 +0000
+++ openlp/core/lib/uistrings.py	2013-03-08 13:50:34 +0000
@@ -122,6 +122,8 @@
         self.Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds')
         self.SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview')
         self.Search = translate('OpenLP.Ui', 'Search')
+        self.SearchLimit = translate('OpenLP.Ui', 'Limit search')
+        self.SearchLimitTip = translate('OpenLP.Ui', 'Only search existing results')
         self.SearchThemes = translate('OpenLP.Ui', 'Search Themes...', 'Search bar place holder text ')
         self.SelectDelete = translate('OpenLP.Ui', 'You must select an item to delete.')
         self.SelectEdit = translate('OpenLP.Ui', 'You must select an item to edit.')

=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
--- openlp/plugins/custom/lib/mediaitem.py	2013-02-19 21:23:56 +0000
+++ openlp/plugins/custom/lib/mediaitem.py	2013-03-08 13:50:34 +0000
@@ -65,6 +65,7 @@
         # which Custom is required.
         self.remoteCustom = -1
         self.manager = plugin.manager
+        self.search_results = []
 
     def addEndHeaderBar(self):
         self.toolbar.addSeparator()
@@ -84,6 +85,8 @@
     def retranslateUi(self):
         self.searchTextLabel.setText(u'%s:' % UiStrings().Search)
         self.searchTextButton.setText(UiStrings().Search)
+        self.searchLimitCheck.setText(UiStrings().SearchLimit)
+        self.searchLimitCheck.setToolTip(UiStrings().SearchLimitTip)
 
     def initialise(self):
         self.searchTextEdit.setSearchTypes([
@@ -212,19 +215,33 @@
         search_keywords = self.searchTextEdit.displayText()
         search_results = []
         search_type = self.searchTextEdit.currentSearchType()
+        search_limit = self.searchLimitCheck.isChecked()
         if search_type == CustomSearch.Titles:
             log.debug(u'Titles Search')
             search_results = self.plugin.manager.get_all_objects(CustomSlide,
                 CustomSlide.title.like(u'%' + self.whitespace.sub(u' ', search_keywords) + u'%'),
                     order_by_ref=CustomSlide.title)
+            if search_limit:
+                search_results = self.limit_search(search_results)
             self.loadList(search_results)
         elif search_type == CustomSearch.Themes:
             log.debug(u'Theme Search')
             search_results = self.plugin.manager.get_all_objects(CustomSlide,
                 CustomSlide.theme_name.like(u'%' + self.whitespace.sub(u' ', search_keywords) + u'%'),
                     order_by_ref=CustomSlide.title)
+            if search_limit:
+                search_results = self.limit_search(search_results)
             self.loadList(search_results)
         self.checkSearchResult()
+        self.search_results = search_results
+
+    def limit_search(self, search_results) :
+        """
+        Filter a search results list to only those that are in the stored search results
+        """
+        current_set = set(self.search_results)
+        results = [result for result in search_results if result in current_set]
+        return results
 
     def onSearchTextEditChanged(self, text):
         """

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2013-03-07 21:04:19 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2013-03-08 13:50:34 +0000
@@ -82,6 +82,7 @@
         self.editItem = None
         self.quickPreviewAllowed = True
         self.hasSearch = True
+        self.search_results = []
 
     def _updateBackgroundAudio(self, song, item):
         song.media_files = []
@@ -127,6 +128,8 @@
     def retranslateUi(self):
         self.searchTextLabel.setText(u'%s:' % UiStrings().Search)
         self.searchTextButton.setText(UiStrings().Search)
+        self.searchLimitCheck.setText(UiStrings().SearchLimit)
+        self.searchLimitCheck.setToolTip(UiStrings().SearchLimitTip)
         self.maintenanceAction.setText(SongStrings.SongMaintenance)
         self.maintenanceAction.setToolTip(translate('SongsPlugin.MediaItem',
             'Maintain the lists of authors, topics and books.'))
@@ -155,6 +158,7 @@
     def onSearchTextButtonClicked(self):
         # Save the current search type to the configuration.
         Settings().setValue(u'%s/last search type' % self.settingsSection, self.searchTextEdit.currentSearchType())
+        search_limit = self.searchLimitCheck.isChecked()
         # Reload the list considering the new search type.
         search_keywords = unicode(self.searchTextEdit.displayText())
         search_results = []
@@ -162,26 +166,36 @@
         if search_type == SongSearch.Entire:
             log.debug(u'Entire Song Search')
             search_results = self.searchEntire(search_keywords)
+            if search_limit:
+                search_results = self.limit_search(search_results)
             self.displayResultsSong(search_results)
         elif search_type == SongSearch.Titles:
             log.debug(u'Titles Search')
             search_results = self.plugin.manager.get_all_objects(Song,
                 Song.search_title.like(u'%' + clean_string(search_keywords) + u'%'))
+            if search_limit :
+                search_results = self.limit_search(search_results)
             self.displayResultsSong(search_results)
         elif search_type == SongSearch.Lyrics:
             log.debug(u'Lyrics Search')
             search_results = self.plugin.manager.get_all_objects(Song,
                 Song.search_lyrics.like(u'%' + clean_string(search_keywords) + u'%'))
+            if search_limit:
+                search_results = self.limit_search(search_results)
             self.displayResultsSong(search_results)
         elif search_type == SongSearch.Authors:
             log.debug(u'Authors Search')
             search_results = self.plugin.manager.get_all_objects(Author,
                 Author.display_name.like(u'%' + search_keywords + u'%'), Author.display_name.asc())
+            if search_limit:
+                search_results = self.limit_search(search_results)
             self.displayResultsAuthor(search_results)
         elif search_type == SongSearch.Books:
             log.debug(u'Books Search')
             search_results = self.plugin.manager.get_all_objects(Book,
                 Book.name.like(u'%' + search_keywords + u'%'), Book.name.asc())
+            if search_limit:
+                search_results = self.limit_search(search_results)
             song_number = False
             if not search_results:
                 search_keywords = search_keywords.rpartition(' ')
@@ -193,7 +207,10 @@
             log.debug(u'Theme Search')
             search_results = self.plugin.manager.get_all_objects(Song,
                 Song.theme_name.like(u'%' + search_keywords + u'%'))
+            if search_limit:
+                search_results = self.limit_search(search_results)
             self.displayResultsSong(search_results)
+        self.search_results = search_results
         self.checkSearchResult()
 
     def searchEntire(self, search_keywords):
@@ -202,6 +219,11 @@
                 Song.search_lyrics.like(u'%' + clean_string(search_keywords) + u'%'),
                 Song.comments.like(u'%' + search_keywords.lower() + u'%')))
 
+    def limit_search(self, search_results) :
+        current_set = set(self.search_results)
+        results = [result for result in search_results if result in current_set]
+        return results
+
     def on_song_list_load(self):
         """
         Handle the exit from the edit dialog and trigger remote updates


Follow ups