openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #08898
[Merge] lp:~j-corwin/openlp/general into lp:openlp
Jonathan Corwin has proposed merging lp:~j-corwin/openlp/general into lp:openlp.
Requested reviews:
OpenLP Core (openlp-core)
Related bugs:
Bug #634771 in OpenLP: "OpenLP 1.9.2+bzr1016-0ubuntu1~lucid1 does not start"
https://bugs.launchpad.net/openlp/+bug/634771
Bug #646718 in OpenLP: "Songbook, Number will not loaded, Title will not be saved"
https://bugs.launchpad.net/openlp/+bug/646718
Bug #696013 in OpenLP: "song import from powerpoint crashes every second time"
https://bugs.launchpad.net/openlp/+bug/696013
Bug #696021 in OpenLP: "presentation loader does not work fine in Windows using Powerpoint Viewer 2007"
https://bugs.launchpad.net/openlp/+bug/696021
Bug #696637 in OpenLP: "Alert not positioned correctly in single screen"
https://bugs.launchpad.net/openlp/+bug/696637
Bug #727732 in OpenLP: "Openlp 1.9.?? crashes on start"
https://bugs.launchpad.net/openlp/+bug/727732
Bug #735039 in OpenLP: "Cannot import PowerPoint Presentations with PowerPoint 2010"
https://bugs.launchpad.net/openlp/+bug/735039
For more details, see:
https://code.launchpad.net/~j-corwin/openlp/general/+merge/61047
Implement a Search and Go-Live option to the Web Remote.
Also made tweaks to the buttons on the slide/service controller on the web remote so they fit on one row on a mobile.
--
https://code.launchpad.net/~j-corwin/openlp/general/+merge/61047
Your team OpenLP Core is requested to review the proposed merge of lp:~j-corwin/openlp/general into lp:openlp.
=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py 2011-05-15 12:11:08 +0000
+++ openlp/core/lib/mediamanageritem.py 2011-05-15 22:21:01 +0000
@@ -102,6 +102,7 @@
self.remoteTriggered = None
self.singleServiceItem = True
self.quickPreviewAllowed = False
+ self.hasSearch = False
self.pageLayout = QtGui.QVBoxLayout(self)
self.pageLayout.setSpacing(0)
self.pageLayout.setMargin(0)
@@ -474,11 +475,23 @@
translate('OpenLP.MediaManagerItem',
'You must select one or more items to send live.'))
else:
- log.debug(u'%s Live requested', self.plugin.name)
- serviceItem = self.buildServiceItem()
- if serviceItem:
+ self.goLive()
+
+ def goLive(self, item_id=None):
+ log.debug(u'%s Live requested', self.plugin.name)
+ item = None
+ if item_id:
+ item = self.createItemFromId(item_id)
+ serviceItem = self.buildServiceItem(item)
+ if serviceItem:
+ if not item_id:
serviceItem.from_plugin = True
- self.parent.liveController.addServiceItem(serviceItem)
+ self.parent.liveController.addServiceItem(serviceItem)
+
+ def createItemFromId(self, item_id):
+ item = QtGui.QListWidgetItem()
+ item.setData(QtCore.Qt.UserRole, QtCore.QVariant(item_id))
+ return item
def onAddClick(self):
"""
@@ -586,3 +599,10 @@
else:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
return item_id
+
+ def search(self, string):
+ """
+ Performs a plugin specific search for items containing ``string``
+ """
+ raise NotImplementedError(
+ u'Plugin.search needs to be defined by the plugin')
=== modified file 'openlp/core/lib/pluginmanager.py'
--- openlp/core/lib/pluginmanager.py 2011-04-14 18:30:53 +0000
+++ openlp/core/lib/pluginmanager.py 2011-05-15 22:21:01 +0000
@@ -211,3 +211,12 @@
if plugin.isActive():
plugin.finalise()
log.info(u'Finalisation Complete for %s ' % plugin.name)
+
+ def get_plugin_by_name(self, name):
+ """
+ Return the plugin which has a name with value ``name``
+ """
+ for plugin in self.plugins:
+ if plugin.name == name:
+ return plugin
+ return None
=== modified file 'openlp/plugins/bibles/lib/db.py'
--- openlp/plugins/bibles/lib/db.py 2011-04-13 18:53:05 +0000
+++ openlp/plugins/bibles/lib/db.py 2011-05-15 22:21:01 +0000
@@ -323,7 +323,7 @@
"""
return self.get_all_objects(Book, order_by_ref=Book.id)
- def get_verses(self, reference_list):
+ def get_verses(self, reference_list, show_error=True):
"""
This is probably the most used function. It retrieves the list of
verses based on the user's query.
@@ -360,11 +360,12 @@
verse_list.extend(verses)
else:
log.debug(u'OpenLP failed to find book %s', book)
- critical_error_message_box(
- translate('BiblesPlugin', 'No Book Found'),
- translate('BiblesPlugin', 'No matching book '
- 'could be found in this Bible. Check that you have '
- 'spelled the name of the book correctly.'))
+ if show_error:
+ critical_error_message_box(
+ translate('BiblesPlugin', 'No Book Found'),
+ translate('BiblesPlugin', 'No matching book '
+ 'could be found in this Bible. Check that you '
+ 'have spelled the name of the book correctly.'))
return verse_list
def verse_search(self, text):
=== modified file 'openlp/plugins/bibles/lib/http.py'
--- openlp/plugins/bibles/lib/http.py 2011-03-24 19:04:02 +0000
+++ openlp/plugins/bibles/lib/http.py 2011-05-15 22:21:01 +0000
@@ -425,7 +425,7 @@
self.create_meta(u'proxy password', self.proxy_password)
return True
- def get_verses(self, reference_list):
+ def get_verses(self, reference_list, show_error=True):
"""
A reimplementation of the ``BibleDB.get_verses`` method, this one is
specifically for web Bibles. It first checks to see if the particular
@@ -453,11 +453,12 @@
if not db_book:
book_details = HTTPBooks.get_book(book)
if not book_details:
- critical_error_message_box(
- translate('BiblesPlugin', 'No Book Found'),
- translate('BiblesPlugin', 'No matching '
- 'book could be found in this Bible. Check that you '
- 'have spelled the name of the book correctly.'))
+ if show_error:
+ critical_error_message_box(
+ translate('BiblesPlugin', 'No Book Found'),
+ translate('BiblesPlugin', 'No matching '
+ 'book could be found in this Bible. Check that you '
+ 'have spelled the name of the book correctly.'))
return []
db_book = self.create_book(book_details[u'name'],
book_details[u'abbreviation'],
@@ -480,7 +481,7 @@
Receiver.send_message(u'openlp_process_events')
Receiver.send_message(u'cursor_normal')
Receiver.send_message(u'openlp_process_events')
- return BibleDB.get_verses(self, reference_list)
+ return BibleDB.get_verses(self, reference_list, show_error)
def get_chapter(self, book, chapter):
"""
=== modified file 'openlp/plugins/bibles/lib/manager.py'
--- openlp/plugins/bibles/lib/manager.py 2011-03-24 19:04:02 +0000
+++ openlp/plugins/bibles/lib/manager.py 2011-05-15 22:21:01 +0000
@@ -231,7 +231,7 @@
bible, book, chapter)
return self.db_cache[bible].get_verse_count(book, chapter)
- def get_verses(self, bible, versetext):
+ def get_verses(self, bible, versetext, show_error=True):
"""
Parses a scripture reference, fetches the verses from the Bible
specified, and returns a list of ``Verse`` objects.
@@ -252,32 +252,34 @@
"""
log.debug(u'BibleManager.get_verses("%s", "%s")', bible, versetext)
if not bible:
- Receiver.send_message(u'openlp_information_message', {
- u'title': translate('BiblesPlugin.BibleManager',
- 'No Bibles Available'),
- u'message': translate('BiblesPlugin.BibleManager',
- 'There are no Bibles currently installed. Please use the '
- 'Import Wizard to install one or more Bibles.')
- })
+ if show_error:
+ Receiver.send_message(u'openlp_information_message', {
+ u'title': translate('BiblesPlugin.BibleManager',
+ 'No Bibles Available'),
+ u'message': translate('BiblesPlugin.BibleManager',
+ 'There are no Bibles currently installed. Please use the '
+ 'Import Wizard to install one or more Bibles.')
+ })
return None
reflist = parse_reference(versetext)
if reflist:
- return self.db_cache[bible].get_verses(reflist)
+ return self.db_cache[bible].get_verses(reflist, show_error)
else:
- Receiver.send_message(u'openlp_information_message', {
- u'title': translate('BiblesPlugin.BibleManager',
- 'Scripture Reference Error'),
- u'message': translate('BiblesPlugin.BibleManager',
- 'Your scripture reference is either not supported by OpenLP '
- 'or is invalid. Please make sure your reference conforms to '
- 'one of the following patterns:\n\n'
- 'Book Chapter\n'
- 'Book Chapter-Chapter\n'
- 'Book Chapter:Verse-Verse\n'
- 'Book Chapter:Verse-Verse,Verse-Verse\n'
- 'Book Chapter:Verse-Verse,Chapter:Verse-Verse\n'
- 'Book Chapter:Verse-Chapter:Verse')
- })
+ if show_message:
+ Receiver.send_message(u'openlp_information_message', {
+ u'title': translate('BiblesPlugin.BibleManager',
+ 'Scripture Reference Error'),
+ u'message': translate('BiblesPlugin.BibleManager',
+ 'Your scripture reference is either not supported by '
+ 'OpenLP or is invalid. Please make sure your reference '
+ 'conforms to one of the following patterns:\n\n'
+ 'Book Chapter\n'
+ 'Book Chapter-Chapter\n'
+ 'Book Chapter:Verse-Verse\n'
+ 'Book Chapter:Verse-Verse,Verse-Verse\n'
+ 'Book Chapter:Verse-Verse,Chapter:Verse-Verse\n'
+ 'Book Chapter:Verse-Chapter:Verse')
+ })
return None
def verse_search(self, bible, second_bible, text):
=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
--- openlp/plugins/bibles/lib/mediaitem.py 2011-05-15 12:11:33 +0000
+++ openlp/plugins/bibles/lib/mediaitem.py 2011-05-15 22:21:01 +0000
@@ -61,6 +61,7 @@
# Place to store the search results for both bibles.
self.settings = self.parent.settings_tab
self.quickPreviewAllowed = True
+ self.hasSearch = True
self.search_results = {}
self.second_search_results = {}
self.check_search_result()
@@ -650,6 +651,19 @@
Displays the search results in the media manager. All data needed for
further action is saved for/in each row.
"""
+ items = self.buildDisplayResults(bible, second_bible,
+ self.search_results)
+ for bible_verse in items:
+ self.listView.addItem(bible_verse)
+ self.listView.selectAll()
+ self.search_results = {}
+ self.second_search_results = {}
+
+ def buildDisplayResults(self, bible, second_bible, search_results):
+ """
+ Displays the search results in the media manager. All data needed for
+ further action is saved for/in each row.
+ """
verse_separator = get_reference_match(u'sep_v_display')
version = self.parent.manager.get_meta_data(bible, u'Version').value
copyright = self.parent.manager.get_meta_data(bible, u'Copyright').value
@@ -665,7 +679,8 @@
second_bible, u'Copyright').value
second_permissions = self.parent.manager.get_meta_data(
second_bible, u'Permissions').value
- for count, verse in enumerate(self.search_results):
+ items = []
+ for count, verse in enumerate(search_results):
data = {
'book': QtCore.QVariant(verse.book.name),
'chapter': QtCore.QVariant(verse.chapter),
@@ -697,10 +712,8 @@
verse.chapter, verse_separator, verse.verse, version)
bible_verse = QtGui.QListWidgetItem(bible_text)
bible_verse.setData(QtCore.Qt.UserRole, QtCore.QVariant(data))
- self.listView.addItem(bible_verse)
- self.listView.selectAll()
- self.search_results = {}
- self.second_search_results = {}
+ items.append(bible_verse)
+ return items
def generateSlideData(self, service_item, item=None, xmlVersion=False):
"""
@@ -708,7 +721,10 @@
service item's title.
"""
log.debug(u'generating slide data')
- items = self.listView.selectedIndexes()
+ if item:
+ items = item
+ else:
+ items = self.listView.selectedItems()
if len(items) == 0:
return False
bible_text = u''
@@ -717,8 +733,7 @@
raw_slides = []
raw_title = []
verses = VerseReferenceList()
- for item in items:
- bitem = self.listView.item(item.row())
+ for bitem in items:
book = self._decodeQtObject(bitem, 'book')
chapter = int(self._decodeQtObject(bitem, 'chapter'))
verse = int(self._decodeQtObject(bitem, 'verse'))
@@ -752,11 +767,11 @@
else:
bible_text = u'%s %s %s\n' % (bible_text, verse_text, text)
if not old_item:
- start_item = item
- elif self.checkTitle(item, old_item):
+ start_item = bitem
+ elif self.checkTitle(bitem, old_item):
raw_title.append(self.formatTitle(start_item, old_item))
- start_item = item
- old_item = item
+ start_item = bitem
+ old_item = bitem
old_chapter = chapter
# Add footer
service_item.raw_footer.append(verses.format_verses())
@@ -764,7 +779,7 @@
verses.add_version(second_version, second_copyright,
second_permissions)
service_item.raw_footer.append(verses.format_versions())
- raw_title.append(self.formatTitle(start_item, item))
+ raw_title.append(self.formatTitle(start_item, bitem))
# If there are no more items we check whether we have to add bible_text.
if bible_text:
raw_slides.append(bible_text.lstrip())
@@ -787,9 +802,9 @@
[service_item.add_from_text(slide[:30], slide) for slide in raw_slides]
return True
- def formatTitle(self, start_item, old_item):
+ def formatTitle(self, start_bitem, old_bitem):
"""
- This methode is called, when we have to change the title, because
+ This method is called, when we have to change the title, because
we are at the end of a verse range. E. g. if we want to add
Genesis 1:1-6 as well as Daniel 2:14.
@@ -801,10 +816,8 @@
"""
verse_separator = get_reference_match(u'sep_v_display')
range_separator = get_reference_match(u'sep_r_display')
- old_bitem = self.listView.item(old_item.row())
old_chapter = self._decodeQtObject(old_bitem, 'chapter')
old_verse = self._decodeQtObject(old_bitem, 'verse')
- start_bitem = self.listView.item(start_item.row())
start_book = self._decodeQtObject(start_bitem, 'book')
start_chapter = self._decodeQtObject(start_bitem, 'chapter')
start_verse = self._decodeQtObject(start_bitem, 'verse')
@@ -825,9 +838,9 @@
range_separator + old_chapter + verse_separator + old_verse
return u'%s %s (%s)' % (start_book, verse_range, bibles)
- def checkTitle(self, item, old_item):
+ def checkTitle(self, bitem, old_bitem):
"""
- This methode checks if we are at the end of an verse range. If that is
+ This method checks if we are at the end of an verse range. If that is
the case, we return True, otherwise False. E. g. if we added
Genesis 1:1-6, but the next verse is Daniel 2:14, we return True.
@@ -838,13 +851,11 @@
The item we were previously dealing with.
"""
# Get all the necessary meta data.
- bitem = self.listView.item(item.row())
book = self._decodeQtObject(bitem, 'book')
chapter = int(self._decodeQtObject(bitem, 'chapter'))
verse = int(self._decodeQtObject(bitem, 'verse'))
bible = self._decodeQtObject(bitem, 'bible')
second_bible = self._decodeQtObject(bitem, 'second_bible')
- old_bitem = self.listView.item(old_item.row())
old_book = self._decodeQtObject(old_bitem, 'book')
old_chapter = int(self._decodeQtObject(old_bitem, 'chapter'))
old_verse = int(self._decodeQtObject(old_bitem, 'verse'))
@@ -896,3 +907,26 @@
if self.settings.display_style == DisplayStyle.Square:
return u'{su}[%s]{/su}' % verse_text
return u'{su}%s{/su}' % verse_text
+
+ def search(self, string):
+ """
+ Search for some Bible verses (by reference).
+ """
+ bible = unicode(self.quickVersionComboBox.currentText())
+ search_results = self.parent.manager.get_verses(bible, string, False)
+ results = []
+ if search_results:
+ versetext = u''
+ for verse in search_results:
+ if versetext:
+ versetext += u' '
+ versetext += verse.text
+ results.append([string, versetext])
+ return results
+
+ def createItemFromId(self, item_id):
+ item = QtGui.QListWidgetItem()
+ bible = unicode(self.quickVersionComboBox.currentText())
+ search_results = self.parent.manager.get_verses(bible, item_id, False)
+ items = self.buildDisplayResults(bible, u'', search_results)
+ return items
=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
--- openlp/plugins/custom/lib/mediaitem.py 2011-04-16 11:42:35 +0000
+++ openlp/plugins/custom/lib/mediaitem.py 2011-05-15 22:21:01 +0000
@@ -27,6 +27,7 @@
import logging
from PyQt4 import QtCore, QtGui
+from sqlalchemy.sql import or_, func
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
check_item_selected
@@ -47,6 +48,7 @@
MediaManagerItem.__init__(self, parent, self, icon)
self.singleServiceItem = False
self.quickPreviewAllowed = True
+ self.hasSearch = True
# Holds information about whether the edit is remotly triggered and
# which Custom is required.
self.remoteCustom = -1
@@ -161,4 +163,16 @@
else:
raw_footer.append(u'')
service_item.raw_footer = raw_footer
- return True
\ No newline at end of file
+ return True
+
+ def search(self, string):
+ search_results = self.manager.get_all_objects(CustomSlide,
+ or_(func.lower(CustomSlide.title).like(u'%' +
+ string.lower() + u'%'),
+ func.lower(CustomSlide.text).like(u'%' +
+ string.lower() + u'%')),
+ order_by_ref=CustomSlide.title)
+ results = []
+ for custom in search_results:
+ results.append([custom.id, custom.title])
+ return results
=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py 2011-04-30 17:36:13 +0000
+++ openlp/plugins/images/lib/mediaitem.py 2011-05-15 22:21:01 +0000
@@ -47,6 +47,7 @@
self.IconPath = u'images/image'
MediaManagerItem.__init__(self, parent, self, icon)
self.quickPreviewAllowed = True
+ self.hasSearch = True
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged)
@@ -130,51 +131,51 @@
self.parent.formparent.finishedProgressBar()
def generateSlideData(self, service_item, item=None, xmlVersion=False):
- items = self.listView.selectedIndexes()
- if items:
- service_item.title = unicode(self.plugin.nameStrings[u'plural'])
- service_item.add_capability(ItemCapabilities.AllowsMaintain)
- service_item.add_capability(ItemCapabilities.AllowsPreview)
- service_item.add_capability(ItemCapabilities.AllowsLoop)
- service_item.add_capability(ItemCapabilities.AllowsAdditions)
- # force a nonexistent theme
- service_item.theme = -1
- missing_items = []
- missing_items_filenames = []
- for item in items:
- bitem = self.listView.item(item.row())
- filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
- if not os.path.exists(filename):
- missing_items.append(item)
- missing_items_filenames.append(filename)
- for item in missing_items:
- items.remove(item)
- # We cannot continue, as all images do not exist.
+ if item:
+ items = [item]
+ else:
+ items = self.listView.selectedItems()
if not items:
- critical_error_message_box(
- translate('ImagePlugin.MediaItem', 'Missing Image(s)'),
- unicode(translate('ImagePlugin.MediaItem',
- 'The following image(s) no longer exist: %s')) %
- u'\n'.join(missing_items_filenames))
return False
- # We have missing as well as existing images. We ask what to do.
- elif missing_items and QtGui.QMessageBox.question(self,
+ service_item.title = unicode(self.plugin.nameStrings[u'plural'])
+ service_item.add_capability(ItemCapabilities.AllowsMaintain)
+ service_item.add_capability(ItemCapabilities.AllowsPreview)
+ service_item.add_capability(ItemCapabilities.AllowsLoop)
+ service_item.add_capability(ItemCapabilities.AllowsAdditions)
+ # force a nonexistent theme
+ service_item.theme = -1
+ missing_items = []
+ missing_items_filenames = []
+ for bitem in items:
+ filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
+ if not os.path.exists(filename):
+ missing_items.append(item)
+ missing_items_filenames.append(filename)
+ for item in missing_items:
+ items.remove(item)
+ # We cannot continue, as all images do not exist.
+ if not items:
+ critical_error_message_box(
translate('ImagePlugin.MediaItem', 'Missing Image(s)'),
- unicode(translate('ImagePlugin.MediaItem', 'The following '
- 'image(s) no longer exist: %s\nDo you want to add the other '
- 'images anyway?')) % u'\n'.join(missing_items_filenames),
- QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
- QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
- return False
- # Continue with the existing images.
- for item in items:
- bitem = self.listView.item(item.row())
- filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
- (path, name) = os.path.split(filename)
- service_item.add_from_image(filename, name)
- return True
- else:
- return False
+ unicode(translate('ImagePlugin.MediaItem',
+ 'The following image(s) no longer exist: %s')) %
+ u'\n'.join(missing_items_filenames))
+ return False
+ # We have missing as well as existing images. We ask what to do.
+ elif missing_items and QtGui.QMessageBox.question(self,
+ translate('ImagePlugin.MediaItem', 'Missing Image(s)'),
+ unicode(translate('ImagePlugin.MediaItem', 'The following '
+ 'image(s) no longer exist: %s\nDo you want to add the other '
+ 'images anyway?')) % u'\n'.join(missing_items_filenames),
+ QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
+ QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
+ return False
+ # Continue with the existing images.
+ for bitem in items:
+ filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
+ (path, name) = os.path.split(filename)
+ service_item.add_from_image(filename, name)
+ return True
def onResetClick(self):
"""
@@ -208,3 +209,14 @@
unicode(translate('ImagePlugin.MediaItem',
'There was a problem replacing your background, '
'the image file "%s" no longer exists.')) % filename)
+
+ def search(self, string):
+ list = SettingsManager.load_list(self.settingsSection,
+ self.settingsSection)
+ results = []
+ string = string.lower()
+ for file in list:
+ filename = os.path.split(unicode(file))[1]
+ if filename.lower().find(string) > -1:
+ results.append([file, filename])
+ return results
=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py 2011-05-01 07:21:55 +0000
+++ openlp/plugins/media/lib/mediaitem.py 2011-05-15 22:21:01 +0000
@@ -50,6 +50,7 @@
u':/media/media_video.png').toImage()
MediaManagerItem.__init__(self, parent, self, icon)
self.singleServiceItem = False
+ self.hasSearch = True
self.mediaObject = None
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'video_background_replaced'),
@@ -212,3 +213,14 @@
log.debug(u'CreatePhonon')
if not self.mediaObject:
self.mediaObject = Phonon.MediaObject(self)
+
+ def search(self, string):
+ list = SettingsManager.load_list(self.settingsSection,
+ self.settingsSection)
+ results = []
+ string = string.lower()
+ for file in list:
+ filename = os.path.split(unicode(file))[1]
+ if filename.lower().find(string) > -1:
+ results.append([file, filename])
+ return results
=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py 2011-04-30 17:36:28 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py 2011-05-15 22:21:01 +0000
@@ -53,6 +53,7 @@
self.Automatic = u''
MediaManagerItem.__init__(self, parent, self, icon)
self.message_listener = MessageListener(self)
+ self.hasSearch = True
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)
@@ -231,17 +232,19 @@
in the slidecontroller. In the case of powerpoints, an image
for each slide
"""
- items = self.listView.selectedIndexes()
- if len(items) > 1:
- return False
+ if item:
+ items = [item]
+ else:
+ items = self.listView.selectedItems()
+ if len(items) > 1:
+ return False
service_item.title = unicode(self.displayTypeComboBox.currentText())
service_item.shortname = unicode(self.displayTypeComboBox.currentText())
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
service_item.add_capability(ItemCapabilities.AllowsDetailedTitleDisplay)
shortname = service_item.shortname
if shortname:
- for item in items:
- bitem = self.listView.item(item.row())
+ for bitem in items:
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
if os.path.exists(filename):
if shortname == self.Automatic:
@@ -303,3 +306,12 @@
if filetype in self.controllers[controller].alsosupports:
return controller
return None
+
+ def search(self, string):
+ list = SettingsManager.load_list(self.settingsSection, u'presentations')
+ results = []
+ string = string.lower()
+ for file in list:
+ if file.lower().find(string) > -1:
+ results.append([file, file])
+ return results
=== modified file 'openlp/plugins/remotes/html/index.html'
--- openlp/plugins/remotes/html/index.html 2011-05-07 08:18:02 +0000
+++ openlp/plugins/remotes/html/index.html 2011-05-15 22:21:01 +0000
@@ -43,6 +43,7 @@
<a href="#service-manager" data-role="button" data-icon="arrow-r" data-iconpos="right">Service Manager</a>
<a href="#slide-controller" data-role="button" data-icon="arrow-r" data-iconpos="right">Slide Controller</a>
<a href="#alerts" data-role="button" data-icon="arrow-r" data-iconpos="right">Alerts</a>
+ <a href="#search" data-role="button" data-icon="arrow-r" data-iconpos="right">Search</a>
</div>
</div>
</div>
@@ -50,6 +51,7 @@
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Service Manager</h1>
+ <a href="#" id="service-refresh" data-role="button" data-icon="refresh">Refresh</a>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true">
@@ -57,9 +59,8 @@
</div>
<div data-role="footer" data-theme="b" class="ui-bar">
<a href="#" id="service-blank" data-role="button" data-icon="blank">Blank</a>
- <a href="#" id="service-unblank" data-role="button" data-icon="unblank">Unblank</a>
- <a href="#" id="service-refresh" data-role="button" data-icon="refresh">Refresh</a>
- <a href="#" id="service-previous" data-role="button" data-icon="arrow-l">Previous</a>
+ <a href="#" id="service-unblank" data-role="button" data-icon="unblank">Show</a>
+ <a href="#" id="service-previous" data-role="button" data-icon="arrow-l">Prev</a>
<a href="#" id="service-next" data-role="button" data-icon="arrow-r" data-iconpos="right">Next</a>
</div>
</div>
@@ -67,6 +68,7 @@
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Slide Controller</h1>
+ <a href="#" id="controller-refresh" data-role="button" data-icon="refresh">Refresh</a>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true">
@@ -74,9 +76,8 @@
</div>
<div data-role="footer" data-theme="b" class="ui-bar">
<a href="#" id="controller-blank" data-role="button" data-icon="blank">Blank</a>
- <a href="#" id="controller-unblank" data-role="button" data-icon="unblank">Unblank</a>
- <a href="#" id="controller-refresh" data-role="button" data-icon="refresh">Refresh</a>
- <a href="#" id="controller-previous" data-role="button" data-icon="arrow-l">Previous</a>
+ <a href="#" id="controller-unblank" data-role="button" data-icon="unblank">Show</a>
+ <a href="#" id="controller-previous" data-role="button" data-icon="arrow-l">Prev</a>
<a href="#" id="controller-next" data-role="button" data-icon="arrow-r" data-iconpos="right">Next</a>
</div>
</div>
@@ -93,5 +94,23 @@
<a href="#" id="alert-submit" data-role="button">Show Alert</a>
</div>
</div>
+<div data-role="page" id="search">
+ <div data-role="header">
+ <a href="#" data-rel="back" data-icon="arrow-l">Back</a>
+ <h1>Search</h1>
+ </div>
+ <div data-role="content">
+ <div data-role="fieldcontain">
+ <label for="search-plugin">Search:</label>
+ <select name="search-plugin" id="search-plugin" data-native-menu="false"></select>
+ </div>
+ <div data-role="fieldcontain">
+ <label for="search-text">Text:</label>
+ <input type="search" name="search-text" id="search-text" value="" />
+ </div>
+ <a href="#" id="search-submit" data-role="button">Search</a>
+ <ul data-role="listview" data-inset="true">
+ </div>
+</div>
</body>
</html>
=== modified file 'openlp/plugins/remotes/html/openlp.js'
--- openlp/plugins/remotes/html/openlp.js 2011-05-08 19:26:32 +0000
+++ openlp/plugins/remotes/html/openlp.js 2011-05-15 22:21:01 +0000
@@ -39,6 +39,19 @@
}
return $(targ);
},
+ searchPlugins: function (event) {
+ $.getJSON(
+ "/api/plugin/search",
+ function (data, status) {
+ var select = $("#search-plugin");
+ select.html("");
+ $.each(data.results.items, function (idx, value) {
+ select.append("<option value='" + value + "'>" + value + "</option>");
+ });
+ select.selectmenu("refresh");
+ }
+ );
+ },
loadService: function (event) {
$.getJSON(
"/api/service/list",
@@ -189,7 +202,43 @@
}
);
return false;
+ },
+ search: function (event) {
+ var text = JSON.stringify({"request": {"text": $("#search-text").val()}});
+ $.getJSON(
+ "/api/" + $("#search-plugin").val() + "/search",
+ {"data": text},
+ function (data, status) {
+ var ul = $("#search > div[data-role=content] > ul[data-role=listview]");
+ ul.html("");
+ if (data.results.items.length == 0) {
+ var li = $("<li data-icon=\"false\">").text('No results');
+ ul.append(li);
+ }
+ else {
+ $.each(data.results.items, function (idx, value) {
+ var li = $("<li data-icon=\"false\">").append(
+ $("<a href=\"#\">").attr("value", value[0]).text(value[1]));
+ li.children("a").click(OpenLP.goLive);
+ ul.append(li);
+ });
+ }
+ ul.listview("refresh");
+ }
+ );
+ return false;
+ },
+ goLive: function (event) {
+ var slide = OpenLP.getElement(event);
+ var id = slide.attr("value");
+ var text = JSON.stringify({"request": {"id": id}});
+ $.getJSON(
+ "/api/" + $("#search-plugin").val() + "/live",
+ {"data": text})
+ $.mobile.changePage("slide-controller");
+ return false;
}
+
}
// Service Manager
$("#service-manager").live("pagebeforeshow", OpenLP.loadService);
@@ -207,7 +256,10 @@
$("#controller-unblank").live("click", OpenLP.unblankDisplay);
// Alerts
$("#alert-submit").live("click", OpenLP.showAlert);
+// Search
+$("#search-submit").live("click", OpenLP.search);
// Poll the server twice a second to get any updates.
+OpenLP.searchPlugins();
$.ajaxSetup({ cache: false });
setInterval("OpenLP.pollServer();", 500);
OpenLP.pollServer();
=== modified file 'openlp/plugins/remotes/lib/httpserver.py'
--- openlp/plugins/remotes/lib/httpserver.py 2011-05-11 23:16:53 +0000
+++ openlp/plugins/remotes/lib/httpserver.py 2011-05-15 22:21:01 +0000
@@ -250,7 +250,10 @@
(r'^/api/controller/(live|preview)/(.*)$', self.controller),
(r'^/api/service/(.*)$', self.service),
(r'^/api/display/(hide|show)$', self.display),
- (r'^/api/alert$', self.alert)
+ (r'^/api/alert$', self.alert),
+ (r'^/api/plugin/(search)$', self.plugin),
+ (r'^/api/(.*)/search$', self.search),
+ (r'^/api/(.*)/live$', self.go_live)
]
QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'readyRead()'),
self.ready_read)
@@ -443,6 +446,49 @@
return HttpResponse(json.dumps({u'results': {u'success': True}}),
{u'Content-Type': u'application/json'})
+ def plugin(self, action):
+ """
+ Return plugin related actions
+
+ ``action`` - The action to perform
+ if 'search' return a list of plugin names which support search
+ """
+ if action == u'search':
+ searches = []
+ for plugin in self.parent.parent.pluginManager.plugins:
+ media_item = plugin.mediaItem
+ if media_item and media_item.hasSearch:
+ searches.append(plugin.name)
+ return HttpResponse(
+ json.dumps({u'results': {u'items': searches}}),
+ {u'Content-Type': u'application/json'})
+
+ def search(self, type):
+ """
+ Return a list of items that match the search text
+
+ ``type``
+ The plugin name to search in.
+ """
+ text = json.loads(self.url_params[u'data'][0])[u'request'][u'text']
+ plugin = self.parent.parent.pluginManager.get_plugin_by_name(type)
+ media_item = plugin.mediaItem
+ if media_item and media_item.hasSearch:
+ results = media_item.search(text)
+ return HttpResponse(
+ json.dumps({u'results': {u'items': results}}),
+ {u'Content-Type': u'application/json'})
+
+ def go_live(self, type):
+ """
+ Go live on an item of type ``type``.
+ """
+ id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
+ plugin = self.parent.parent.pluginManager.get_plugin_by_name(type)
+ media_item = plugin.mediaItem
+ if media_item:
+ media_item.goLive(id)
+
def send_response(self, response):
http = u'HTTP/1.1 %s\r\n' % response.code
for header, value in response.headers.iteritems():
=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py 2011-05-15 12:11:08 +0000
+++ openlp/plugins/songs/lib/mediaitem.py 2011-05-15 22:21:01 +0000
@@ -74,6 +74,7 @@
self.editItem = None
self.whitespace = re.compile(r'\W+', re.UNICODE)
self.quickPreviewAllowed = True
+ self.hasSearch = True
def addEndHeaderBar(self):
self.addToolbarSeparator()
@@ -171,11 +172,7 @@
search_type = self.searchTextEdit.currentSearchType()
if search_type == SongSearch.Entire:
log.debug(u'Entire Song Search')
- search_results = self.parent.manager.get_all_objects(Song,
- or_(Song.search_title.like(u'%' + self.whitespace.sub(u' ',
- search_keywords.lower()) + u'%'),
- Song.search_lyrics.like(u'%' + search_keywords.lower() + u'%'),
- Song.comments.like(u'%' + search_keywords.lower() + u'%')))
+ search_results = self.searchEntire(search_keywords)
self.displayResultsSong(search_results)
elif search_type == SongSearch.Titles:
log.debug(u'Titles Search')
@@ -201,6 +198,13 @@
self.displayResultsSong(search_results)
self.check_search_result()
+ def searchEntire(self, search_keywords):
+ return self.parent.manager.get_all_objects(Song,
+ or_(Song.search_title.like(u'%' + self.whitespace.sub(u' ',
+ search_keywords.lower()) + u'%'),
+ Song.search_lyrics.like(u'%' + search_keywords.lower() + u'%'),
+ Song.comments.like(u'%' + search_keywords.lower() + u'%')))
+
def onSongListLoad(self):
"""
Handle the exit from the edit dialog and trigger remote updates
@@ -217,7 +221,8 @@
# Push edits to the service manager to update items
if self.editItem and self.updateServiceOnEdit and \
not self.remoteTriggered:
- item = self.buildServiceItem(self.editItem)
+ item_id = _getIdOfItemToGenerate(self.editItem)
+ item = self.buildServiceItem(item_id)
self.parent.serviceManager.replaceServiceItem(item)
self.onRemoteEditClear()
self.onSearchTextButtonClick()
@@ -475,3 +480,13 @@
"""
return locale.strcoll(unicode(song_1.title.lower()),
unicode(song_2.title.lower()))
+
+ def search(self, string):
+ """
+ Search for some songs
+ """
+ search_results = self.searchEntire(string)
+ results = []
+ for song in search_results:
+ results.append([song.id, song.title])
+ return results
=== modified file 'openlp/plugins/songs/songsplugin.py'
--- openlp/plugins/songs/songsplugin.py 2011-05-07 11:06:43 +0000
+++ openlp/plugins/songs/songsplugin.py 2011-05-15 22:21:01 +0000
@@ -268,4 +268,3 @@
action_list.remove_action(self.songExportItem, UiStrings().Export)
action_list.remove_action(self.toolsReindexItem, UiStrings().Tools)
Plugin.finalise(self)
-
Follow ups