forked from openlp/openlp
r1552
This commit is contained in:
commit
856689e72c
@ -102,6 +102,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
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 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
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 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
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')
|
||||
|
@ -211,3 +211,12 @@ class PluginManager(object):
|
||||
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
|
||||
|
@ -323,7 +323,7 @@ class BibleDB(QtCore.QObject, Manager):
|
||||
"""
|
||||
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 @@ class BibleDB(QtCore.QObject, Manager):
|
||||
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):
|
||||
|
@ -425,7 +425,7 @@ class HTTPBible(BibleDB):
|
||||
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 @@ class HTTPBible(BibleDB):
|
||||
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 @@ class HTTPBible(BibleDB):
|
||||
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):
|
||||
"""
|
||||
|
@ -231,7 +231,7 @@ class BibleManager(object):
|
||||
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 @@ class BibleManager(object):
|
||||
"""
|
||||
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_error:
|
||||
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):
|
||||
|
@ -61,6 +61,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
# 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()
|
||||
@ -646,6 +647,19 @@ class BibleMediaItem(MediaManagerItem):
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
|
||||
def displayResults(self, bible, second_bible=u''):
|
||||
"""
|
||||
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.
|
||||
@ -665,7 +679,8 @@ class BibleMediaItem(MediaManagerItem):
|
||||
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 @@ class BibleMediaItem(MediaManagerItem):
|
||||
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 @@ class BibleMediaItem(MediaManagerItem):
|
||||
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 @@ class BibleMediaItem(MediaManagerItem):
|
||||
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 @@ class BibleMediaItem(MediaManagerItem):
|
||||
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 @@ class BibleMediaItem(MediaManagerItem):
|
||||
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 @@ class BibleMediaItem(MediaManagerItem):
|
||||
[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 @@ class BibleMediaItem(MediaManagerItem):
|
||||
"""
|
||||
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 @@ class BibleMediaItem(MediaManagerItem):
|
||||
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 @@ class BibleMediaItem(MediaManagerItem):
|
||||
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,22 @@ class BibleMediaItem(MediaManagerItem):
|
||||
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' '.join([verse.text for verse in search_results])
|
||||
return [[string, versetext]]
|
||||
return []
|
||||
|
||||
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
|
||||
|
@ -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 @@ class CustomMediaItem(MediaManagerItem):
|
||||
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
|
||||
@ -162,3 +164,15 @@ class CustomMediaItem(MediaManagerItem):
|
||||
raw_footer.append(u'')
|
||||
service_item.raw_footer = raw_footer
|
||||
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
|
||||
|
@ -47,6 +47,7 @@ class ImageMediaItem(MediaManagerItem):
|
||||
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 @@ class ImageMediaItem(MediaManagerItem):
|
||||
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 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,
|
||||
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
|
||||
if item:
|
||||
items = [item]
|
||||
else:
|
||||
items = self.listView.selectedItems()
|
||||
if not items:
|
||||
return False
|
||||
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')) %
|
||||
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 @@ class ImageMediaItem(MediaManagerItem):
|
||||
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
|
||||
|
@ -50,6 +50,7 @@ class MediaMediaItem(MediaManagerItem):
|
||||
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 @@ class MediaMediaItem(MediaManagerItem):
|
||||
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
|
||||
|
@ -53,6 +53,7 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
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 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
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 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
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
|
||||
|
@ -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>
|
||||
|
@ -39,6 +39,19 @@ window.OpenLP = {
|
||||
}
|
||||
return $(targ);
|
||||
},
|
||||
getSearchablePlugins: 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",
|
||||
@ -63,7 +76,9 @@ window.OpenLP = {
|
||||
var ul = $("#slide-controller > div[data-role=content] > ul[data-role=listview]");
|
||||
ul.html("");
|
||||
for (idx in data.results.slides) {
|
||||
var text = data.results.slides[idx]["text"];
|
||||
var text = data.results.slides[idx]["tag"];
|
||||
if (text != "") text = text + ": ";
|
||||
text = text + data.results.slides[idx]["text"];
|
||||
text = text.replace(/\n/g, '<br />');
|
||||
var li = $("<li data-icon=\"false\">").append(
|
||||
$("<a href=\"#\">").attr("value", parseInt(idx, 10)).html(text));
|
||||
@ -189,7 +204,43 @@ window.OpenLP = {
|
||||
}
|
||||
);
|
||||
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 +258,10 @@ $("#controller-blank").live("click", OpenLP.blankDisplay);
|
||||
$("#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.getSearchablePlugins();
|
||||
$.ajaxSetup({ cache: false });
|
||||
setInterval("OpenLP.pollServer();", 500);
|
||||
OpenLP.pollServer();
|
||||
|
@ -123,7 +123,7 @@ except ImportError:
|
||||
|
||||
from PyQt4 import QtCore, QtNetwork
|
||||
|
||||
from openlp.core.lib import Receiver
|
||||
from openlp.core.lib import Receiver, PluginStatus
|
||||
from openlp.core.ui import HideMode
|
||||
from openlp.core.utils import AppLocation
|
||||
|
||||
@ -250,7 +250,10 @@ class HttpConnection(object):
|
||||
(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.pluginInfo),
|
||||
(r'^/api/(.*)/search$', self.search),
|
||||
(r'^/api/(.*)/live$', self.go_live)
|
||||
]
|
||||
QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'readyRead()'),
|
||||
self.ready_read)
|
||||
@ -409,8 +412,8 @@ class HttpConnection(object):
|
||||
item[u'html'] = unicode(frame[u'html'])
|
||||
else:
|
||||
item[u'tag'] = unicode(index + 1)
|
||||
item[u'text'] = u''
|
||||
item[u'html'] = u''
|
||||
item[u'text'] = unicode(frame[u'title'])
|
||||
item[u'html'] = unicode(frame[u'title'])
|
||||
item[u'selected'] = (self.parent.current_slide == index)
|
||||
data.append(item)
|
||||
json_data = {u'results': {u'slides': data}}
|
||||
@ -443,6 +446,50 @@ class HttpConnection(object):
|
||||
return HttpResponse(json.dumps({u'results': {u'success': True}}),
|
||||
{u'Content-Type': u'application/json'})
|
||||
|
||||
def pluginInfo(self, action):
|
||||
"""
|
||||
Return plugin related information, based on the action
|
||||
|
||||
``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:
|
||||
if plugin.status == PluginStatus.Active and \
|
||||
plugin.mediaItem and plugin.mediaItem.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)
|
||||
if plugin.status == PluginStatus.Active and \
|
||||
plugin.mediaItem and plugin.mediaItem.hasSearch:
|
||||
results =plugin.mediaItem.search(text)
|
||||
else:
|
||||
results = []
|
||||
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)
|
||||
if plugin.status == PluginStatus.Active and plugin.mediaItem:
|
||||
plugin.mediaItem.goLive(id)
|
||||
|
||||
def send_response(self, response):
|
||||
http = u'HTTP/1.1 %s\r\n' % response.code
|
||||
for header, value in response.headers.iteritems():
|
||||
|
@ -74,6 +74,7 @@ class SongMediaItem(MediaManagerItem):
|
||||
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 @@ class SongMediaItem(MediaManagerItem):
|
||||
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 @@ class SongMediaItem(MediaManagerItem):
|
||||
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 @@ class SongMediaItem(MediaManagerItem):
|
||||
# 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 @@ class SongMediaItem(MediaManagerItem):
|
||||
"""
|
||||
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
|
||||
|
@ -268,4 +268,3 @@ class SongsPlugin(Plugin):
|
||||
action_list.remove_action(self.songExportItem, UiStrings().Export)
|
||||
action_list.remove_action(self.toolsReindexItem, UiStrings().Tools)
|
||||
Plugin.finalise(self)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user