This commit is contained in:
Andreas Preikschat 2011-05-18 16:06:33 +02:00
commit a56f98baee
22 changed files with 531 additions and 267 deletions

View File

@ -223,28 +223,6 @@ def resize_image(image, width, height, background=QtCore.Qt.black):
painter.drawImage((width - realw) / 2, (height - realh) / 2, preview) painter.drawImage((width - realw) / 2, (height - realh) / 2, preview)
return new_image return new_image
def check_search_result(treeWidget, search_results):
"""
Checks if the given ``search_results`` is empty and adds a
"No Search Results" item to the given ``treeWidget``.
``treeWidget``
The ``QTreeWidget`` where the "No Search Results" item should be added
to, if the ``search_results`` is empty.
``search_results``
This can either be a list or a dict.
"""
if search_results or treeWidget.count():
return
message = translate('OpenLP.MediaManagerItem', 'No Search Results')
item = QtGui.QListWidgetItem(message)
item.setFlags(QtCore.Qt.NoItemFlags)
font = QtGui.QFont()
font.setItalic(True)
item.setFont(font)
treeWidget.addItem(item)
def check_item_selected(list_widget, message): def check_item_selected(list_widget, message):
""" """
Check if a list item is selected so an action may be performed on it Check if a list item is selected so an action may be performed on it

View File

@ -102,6 +102,7 @@ class MediaManagerItem(QtGui.QWidget):
self.remoteTriggered = None self.remoteTriggered = None
self.singleServiceItem = True self.singleServiceItem = True
self.quickPreviewAllowed = False self.quickPreviewAllowed = False
self.hasSearch = False
self.pageLayout = QtGui.QVBoxLayout(self) self.pageLayout = QtGui.QVBoxLayout(self)
self.pageLayout.setSpacing(0) self.pageLayout.setSpacing(0)
self.pageLayout.setMargin(0) self.pageLayout.setMargin(0)
@ -244,7 +245,6 @@ class MediaManagerItem(QtGui.QWidget):
""" """
# Add the List widget # Add the List widget
self.listView = ListWidgetWithDnD(self, self.plugin.name) self.listView = ListWidgetWithDnD(self, self.plugin.name)
self.listView.setUniformItemSizes(True)
self.listView.setSpacing(1) self.listView.setSpacing(1)
self.listView.setSelectionMode( self.listView.setSelectionMode(
QtGui.QAbstractItemView.ExtendedSelection) QtGui.QAbstractItemView.ExtendedSelection)
@ -475,12 +475,24 @@ class MediaManagerItem(QtGui.QWidget):
translate('OpenLP.MediaManagerItem', translate('OpenLP.MediaManagerItem',
'You must select one or more items to send live.')) 'You must select one or more items to send live.'))
else: else:
self.goLive()
def goLive(self, item_id=None):
log.debug(u'%s Live requested', self.plugin.name) log.debug(u'%s Live requested', self.plugin.name)
serviceItem = self.buildServiceItem() item = None
if item_id:
item = self.createItemFromId(item_id)
serviceItem = self.buildServiceItem(item)
if serviceItem: if serviceItem:
if not item_id:
serviceItem.from_plugin = True 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): def onAddClick(self):
""" """
Add a selected item to the current service Add a selected item to the current service
@ -552,6 +564,20 @@ class MediaManagerItem(QtGui.QWidget):
""" """
pass pass
def check_search_result(self):
"""
Checks if the listView is empty and adds a "No Search Results" item.
"""
if self.listView.count():
return
message = translate('OpenLP.MediaManagerItem', 'No Search Results')
item = QtGui.QListWidgetItem(message)
item.setFlags(QtCore.Qt.NoItemFlags)
font = QtGui.QFont()
font.setItalic(True)
item.setFont(font)
self.listView.addItem(item)
def _getIdOfItemToGenerate(self, item, remoteItem): def _getIdOfItemToGenerate(self, item, remoteItem):
""" """
Utility method to check items being submitted for slide generation. Utility method to check items being submitted for slide generation.
@ -573,3 +599,10 @@ class MediaManagerItem(QtGui.QWidget):
else: else:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
return item_id 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')

View File

@ -211,3 +211,12 @@ class PluginManager(object):
if plugin.isActive(): if plugin.isActive():
plugin.finalise() plugin.finalise()
log.info(u'Finalisation Complete for %s ' % plugin.name) 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

View File

@ -162,6 +162,8 @@ class Renderer(object):
self.theme_data = self.theme_manager.getThemeData(theme) self.theme_data = self.theme_manager.getThemeData(theme)
self._calculate_default(self.screens.current[u'size']) self._calculate_default(self.screens.current[u'size'])
self._build_text_rectangle(self.theme_data) self._build_text_rectangle(self.theme_data)
# if No file do not update cache
if self.theme_data.background_filename:
self.image_manager.add_image(self.theme_data.theme_name, self.image_manager.add_image(self.theme_data.theme_name,
self.theme_data.background_filename) self.theme_data.background_filename)
return self._rect, self._rect_footer return self._rect, self._rect_footer
@ -298,7 +300,7 @@ class Renderer(object):
# Adjust width and height to account for shadow. outline done in css # Adjust width and height to account for shadow. outline done in css
self.page_shell = u'<html><head><style>' \ self.page_shell = u'<html><head><style>' \
u'*{margin: 0; padding: 0; border: 0;} '\ u'*{margin: 0; padding: 0; border: 0;} '\
u'#main {position:absolute; top:0px; %s %s}</style><body>' \ u'#main {position:absolute; top:0px; %s %s}</style></head><body>' \
u'<div id="main">' % \ u'<div id="main">' % \
(build_lyrics_format_css(self.theme_data, self.page_width, (build_lyrics_format_css(self.theme_data, self.page_width,
self.page_height), build_lyrics_outline_css(self.theme_data)) self.page_height), build_lyrics_outline_css(self.theme_data))

View File

@ -50,7 +50,6 @@ class SettingsTab(QtGui.QWidget):
self.setupUi() self.setupUi()
self.retranslateUi() self.retranslateUi()
self.initialise() self.initialise()
self.preLoad()
self.load() self.load()
def setupUi(self): def setupUi(self):
@ -86,12 +85,6 @@ class SettingsTab(QtGui.QWidget):
left_width = max(left_width, self.leftColumn.minimumSizeHint().width()) left_width = max(left_width, self.leftColumn.minimumSizeHint().width())
self.leftColumn.setFixedWidth(left_width) self.leftColumn.setFixedWidth(left_width)
def preLoad(self):
"""
Setup the tab's interface.
"""
pass
def retranslateUi(self): def retranslateUi(self):
""" """
Setup the interface translation strings. Setup the interface translation strings.
@ -118,9 +111,9 @@ class SettingsTab(QtGui.QWidget):
def cancel(self): def cancel(self):
""" """
Reset any settings Reset any settings if cancel pressed
""" """
pass self.load()
def postSetUp(self, postUpdate=False): def postSetUp(self, postUpdate=False):
""" """

View File

@ -47,7 +47,7 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
""" """
QtGui.QDialog.__init__(self, parent) QtGui.QDialog.__init__(self, parent)
self.setupUi(self) self.setupUi(self)
self.preLoad() self._loadDisplayTags()
QtCore.QObject.connect(self.tagTableWidget, QtCore.QObject.connect(self.tagTableWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected) QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected)
QtCore.QObject.connect(self.defaultPushButton, QtCore.QObject.connect(self.defaultPushButton,
@ -66,12 +66,12 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
Load Display and set field state. Load Display and set field state.
""" """
# Create initial copy from master # Create initial copy from master
self.preLoad() self._loadDisplayTags()
self._resetTable() self._resetTable()
self.selected = -1 self.selected = -1
return QtGui.QDialog.exec_(self) return QtGui.QDialog.exec_(self)
def preLoad(self): def _loadDisplayTags(self):
""" """
Load the Tags from store so can be used in the system or used to Load the Tags from store so can be used in the system or used to
update the display. If Cancel was selected this is needed to reset the update the display. If Cancel was selected this is needed to reset the

View File

@ -101,6 +101,7 @@ class GeneralTab(SettingsTab):
self.timeoutLabel.setObjectName(u'timeoutLabel') self.timeoutLabel.setObjectName(u'timeoutLabel')
self.timeoutSpinBox = QtGui.QSpinBox(self.settingsGroupBox) self.timeoutSpinBox = QtGui.QSpinBox(self.settingsGroupBox)
self.timeoutSpinBox.setObjectName(u'timeoutSpinBox') self.timeoutSpinBox.setObjectName(u'timeoutSpinBox')
self.timeoutSpinBox.setRange(1, 180)
self.settingsLayout.addRow(self.timeoutLabel, self.timeoutSpinBox) self.settingsLayout.addRow(self.timeoutLabel, self.timeoutSpinBox)
self.leftLayout.addWidget(self.settingsGroupBox) self.leftLayout.addWidget(self.settingsGroupBox)
self.leftLayout.addStretch() self.leftLayout.addStretch()

View File

@ -199,8 +199,7 @@ class SlideController(QtGui.QWidget):
'Start/Stop continuous loop')) 'Start/Stop continuous loop'))
self.addAction(self.toogleLoop) self.addAction(self.toogleLoop)
self.delaySpinBox = QtGui.QSpinBox() self.delaySpinBox = QtGui.QSpinBox()
self.delaySpinBox.setMinimum(1) self.delaySpinBox.setRange(1, 180)
self.delaySpinBox.setMaximum(180)
self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox) self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox)
self.delaySpinBox.setSuffix(UiStrings().Seconds) self.delaySpinBox.setSuffix(UiStrings().Seconds)
self.delaySpinBox.setToolTip(translate('OpenLP.SlideController', self.delaySpinBox.setToolTip(translate('OpenLP.SlideController',

View File

@ -323,7 +323,7 @@ class BibleDB(QtCore.QObject, Manager):
""" """
return self.get_all_objects(Book, order_by_ref=Book.id) 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 This is probably the most used function. It retrieves the list of
verses based on the user's query. verses based on the user's query.
@ -360,11 +360,12 @@ class BibleDB(QtCore.QObject, Manager):
verse_list.extend(verses) verse_list.extend(verses)
else: else:
log.debug(u'OpenLP failed to find book %s', book) log.debug(u'OpenLP failed to find book %s', book)
if show_error:
critical_error_message_box( critical_error_message_box(
translate('BiblesPlugin', 'No Book Found'), translate('BiblesPlugin', 'No Book Found'),
translate('BiblesPlugin', 'No matching book ' translate('BiblesPlugin', 'No matching book '
'could be found in this Bible. Check that you have ' 'could be found in this Bible. Check that you '
'spelled the name of the book correctly.')) 'have spelled the name of the book correctly.'))
return verse_list return verse_list
def verse_search(self, text): def verse_search(self, text):

View File

@ -425,7 +425,7 @@ class HTTPBible(BibleDB):
self.create_meta(u'proxy password', self.proxy_password) self.create_meta(u'proxy password', self.proxy_password)
return True 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 A reimplementation of the ``BibleDB.get_verses`` method, this one is
specifically for web Bibles. It first checks to see if the particular specifically for web Bibles. It first checks to see if the particular
@ -453,6 +453,7 @@ class HTTPBible(BibleDB):
if not db_book: if not db_book:
book_details = HTTPBooks.get_book(book) book_details = HTTPBooks.get_book(book)
if not book_details: if not book_details:
if show_error:
critical_error_message_box( critical_error_message_box(
translate('BiblesPlugin', 'No Book Found'), translate('BiblesPlugin', 'No Book Found'),
translate('BiblesPlugin', 'No matching ' translate('BiblesPlugin', 'No matching '
@ -480,7 +481,7 @@ class HTTPBible(BibleDB):
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
Receiver.send_message(u'openlp_process_events') 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): def get_chapter(self, book, chapter):
""" """

View File

@ -231,7 +231,7 @@ class BibleManager(object):
bible, book, chapter) bible, book, chapter)
return self.db_cache[bible].get_verse_count(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 Parses a scripture reference, fetches the verses from the Bible
specified, and returns a list of ``Verse`` objects. specified, and returns a list of ``Verse`` objects.
@ -252,6 +252,7 @@ class BibleManager(object):
""" """
log.debug(u'BibleManager.get_verses("%s", "%s")', bible, versetext) log.debug(u'BibleManager.get_verses("%s", "%s")', bible, versetext)
if not bible: if not bible:
if show_error:
Receiver.send_message(u'openlp_information_message', { Receiver.send_message(u'openlp_information_message', {
u'title': translate('BiblesPlugin.BibleManager', u'title': translate('BiblesPlugin.BibleManager',
'No Bibles Available'), 'No Bibles Available'),
@ -262,15 +263,16 @@ class BibleManager(object):
return None return None
reflist = parse_reference(versetext) reflist = parse_reference(versetext)
if reflist: if reflist:
return self.db_cache[bible].get_verses(reflist) return self.db_cache[bible].get_verses(reflist, show_error)
else: else:
if show_error:
Receiver.send_message(u'openlp_information_message', { Receiver.send_message(u'openlp_information_message', {
u'title': translate('BiblesPlugin.BibleManager', u'title': translate('BiblesPlugin.BibleManager',
'Scripture Reference Error'), 'Scripture Reference Error'),
u'message': translate('BiblesPlugin.BibleManager', u'message': translate('BiblesPlugin.BibleManager',
'Your scripture reference is either not supported by OpenLP ' 'Your scripture reference is either not supported by '
'or is invalid. Please make sure your reference conforms to ' 'OpenLP or is invalid. Please make sure your reference '
'one of the following patterns:\n\n' 'conforms to one of the following patterns:\n\n'
'Book Chapter\n' 'Book Chapter\n'
'Book Chapter-Chapter\n' 'Book Chapter-Chapter\n'
'Book Chapter:Verse-Verse\n' 'Book Chapter:Verse-Verse\n'
@ -285,7 +287,7 @@ class BibleManager(object):
Does a verse search for the given bible and text. Does a verse search for the given bible and text.
``bible`` ``bible``
The bible to seach in (unicode). The bible to search in (unicode).
``second_bible`` ``second_bible``
The second bible (unicode). We do not search in this bible. The second bible (unicode). We do not search in this bible.
@ -294,6 +296,15 @@ class BibleManager(object):
The text to search for (unicode). The text to search for (unicode).
""" """
log.debug(u'BibleManager.verse_search("%s", "%s")', bible, text) log.debug(u'BibleManager.verse_search("%s", "%s")', bible, text)
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.')
})
return None
# Check if the bible or second_bible is a web bible. # Check if the bible or second_bible is a web bible.
webbible = self.db_cache[bible].get_object(BibleMeta, webbible = self.db_cache[bible].get_object(BibleMeta,
u'download source') u'download source')

View File

@ -29,7 +29,7 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
translate, check_search_result translate
from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import UiStrings, add_widget_completer, \ from openlp.core.lib.ui import UiStrings, add_widget_completer, \
media_item_combo_box, critical_error_message_box, find_and_set_in_combo_box media_item_combo_box, critical_error_message_box, find_and_set_in_combo_box
@ -61,12 +61,46 @@ class BibleMediaItem(MediaManagerItem):
# Place to store the search results for both bibles. # Place to store the search results for both bibles.
self.settings = self.parent.settings_tab self.settings = self.parent.settings_tab
self.quickPreviewAllowed = True self.quickPreviewAllowed = True
self.hasSearch = True
self.search_results = {} self.search_results = {}
self.second_search_results = {} self.second_search_results = {}
check_search_result(self.listView, self.search_results) self.check_search_result()
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'bibles_load_list'), self.reloadBibles) QtCore.SIGNAL(u'bibles_load_list'), self.reloadBibles)
def __checkSecondBible(self, bible, second_bible):
"""
Check if the first item is a second bible item or not.
"""
bitem = self.listView.item(0)
if not bitem.flags() & QtCore.Qt.ItemIsSelectable:
# The item is the "No Search Results" item.
self.listView.clear()
self.displayResults(bible, second_bible)
return
else:
item_second_bible = self._decodeQtObject(bitem, 'second_bible')
if item_second_bible and second_bible or not item_second_bible and \
not second_bible:
self.displayResults(bible, second_bible)
elif critical_error_message_box(
message=translate('BiblePlugin.MediaItem',
'You cannot combine single and dual Bible verse search results. '
'Do you want to delete your search results and start a new '
'search?'),
parent=self, question=True) == QtGui.QMessageBox.Yes:
self.listView.clear()
self.displayResults(bible, second_bible)
def _decodeQtObject(self, bitem, key):
reference = bitem.data(QtCore.Qt.UserRole)
if isinstance(reference, QtCore.QVariant):
reference = reference.toPyObject()
obj = reference[QtCore.QString(key)]
if isinstance(obj, QtCore.QVariant):
obj = obj.toPyObject()
return unicode(obj).strip()
def requiredIcons(self): def requiredIcons(self):
MediaManagerItem.requiredIcons(self) MediaManagerItem.requiredIcons(self)
self.hasImportIcon = True self.hasImportIcon = True
@ -114,6 +148,12 @@ class BibleMediaItem(MediaManagerItem):
secondComboBox = media_item_combo_box(tab, prefix + u'SecondComboBox') secondComboBox = media_item_combo_box(tab, prefix + u'SecondComboBox')
versionLabel.setBuddy(secondComboBox) versionLabel.setBuddy(secondComboBox)
layout.addWidget(secondComboBox, idx + 1, 1, 1, 2) layout.addWidget(secondComboBox, idx + 1, 1, 1, 2)
styleLabel = QtGui.QLabel(tab)
styleLabel.setObjectName(prefix + u'StyleLabel')
layout.addWidget(styleLabel, idx + 2, 0, QtCore.Qt.AlignRight)
styleComboBox = media_item_combo_box(tab, prefix + u'StyleComboBox')
styleComboBox.addItems([u'', u'', u''])
layout.addWidget(styleComboBox, idx + 2, 1, 1, 2)
searchButtonLayout = QtGui.QHBoxLayout() searchButtonLayout = QtGui.QHBoxLayout()
searchButtonLayout.setObjectName(prefix + u'SearchButtonLayout') searchButtonLayout.setObjectName(prefix + u'SearchButtonLayout')
searchButtonLayout.addStretch() searchButtonLayout.addStretch()
@ -125,7 +165,7 @@ class BibleMediaItem(MediaManagerItem):
searchButton = QtGui.QPushButton(tab) searchButton = QtGui.QPushButton(tab)
searchButton.setObjectName(prefix + u'SearchButton') searchButton.setObjectName(prefix + u'SearchButton')
searchButtonLayout.addWidget(searchButton) searchButtonLayout.addWidget(searchButton)
layout.addLayout(searchButtonLayout, idx + 2, 1, 1, 2) layout.addLayout(searchButtonLayout, idx + 3, 1, 1, 2)
self.pageLayout.addWidget(tab) self.pageLayout.addWidget(tab)
tab.setVisible(False) tab.setVisible(False)
QtCore.QObject.connect(lockButton, QtCore.SIGNAL(u'toggled(bool)'), QtCore.QObject.connect(lockButton, QtCore.SIGNAL(u'toggled(bool)'),
@ -134,6 +174,8 @@ class BibleMediaItem(MediaManagerItem):
setattr(self, prefix + u'VersionComboBox', versionComboBox) setattr(self, prefix + u'VersionComboBox', versionComboBox)
setattr(self, prefix + u'SecondLabel', secondLabel) setattr(self, prefix + u'SecondLabel', secondLabel)
setattr(self, prefix + u'SecondComboBox', secondComboBox) setattr(self, prefix + u'SecondComboBox', secondComboBox)
setattr(self, prefix + u'StyleLabel', styleLabel)
setattr(self, prefix + u'StyleComboBox', styleComboBox)
setattr(self, prefix + u'LockButton', lockButton) setattr(self, prefix + u'LockButton', lockButton)
setattr(self, prefix + u'SearchButtonLayout', searchButtonLayout) setattr(self, prefix + u'SearchButtonLayout', searchButtonLayout)
setattr(self, prefix + u'SearchButton', searchButton) setattr(self, prefix + u'SearchButton', searchButton)
@ -154,14 +196,6 @@ class BibleMediaItem(MediaManagerItem):
self.quickSearchEdit.setObjectName(u'quickSearchEdit') self.quickSearchEdit.setObjectName(u'quickSearchEdit')
self.quickSearchLabel.setBuddy(self.quickSearchEdit) self.quickSearchLabel.setBuddy(self.quickSearchEdit)
self.quickLayout.addWidget(self.quickSearchEdit, 0, 1, 1, 2) self.quickLayout.addWidget(self.quickSearchEdit, 0, 1, 1, 2)
self.quickLayoutLabel = QtGui.QLabel(self.quickTab)
self.quickLayoutLabel.setObjectName(u'quickClearLabel')
self.quickLayout.addWidget(
self.quickLayoutLabel, 1, 0, QtCore.Qt.AlignRight)
self.quickLayoutComboBox = media_item_combo_box(self.quickTab,
u'quickLayoutComboBox')
self.quickLayoutComboBox.addItems([u'', u'', u''])
self.quickLayout.addWidget(self.quickLayoutComboBox, 1, 1, 1, 2)
self.addSearchFields( self.addSearchFields(
u'quick', translate('BiblesPlugin.MediaItem', 'Quick')) u'quick', translate('BiblesPlugin.MediaItem', 'Quick'))
self.quickTab.setVisible(True) self.quickTab.setVisible(True)
@ -218,8 +252,11 @@ class BibleMediaItem(MediaManagerItem):
QtCore.QObject.connect(self.quickVersionComboBox, QtCore.QObject.connect(self.quickVersionComboBox,
QtCore.SIGNAL(u'activated(int)'), self.updateAutoCompleter) QtCore.SIGNAL(u'activated(int)'), self.updateAutoCompleter)
QtCore.QObject.connect( QtCore.QObject.connect(
self.quickLayoutComboBox, QtCore.SIGNAL(u'activated(int)'), self.quickStyleComboBox, QtCore.SIGNAL(u'activated(int)'),
self.onLayoutStyleComboBoxChanged) self.onQuickStyleComboBoxChanged)
QtCore.QObject.connect(
self.advancedStyleComboBox, QtCore.SIGNAL(u'activated(int)'),
self.onAdvancedStyleComboBoxChanged)
# Buttons # Buttons
QtCore.QObject.connect(self.advancedSearchButton, QtCore.QObject.connect(self.advancedSearchButton,
QtCore.SIGNAL(u'pressed()'), self.onAdvancedSearchButton) QtCore.SIGNAL(u'pressed()'), self.onAdvancedSearchButton)
@ -247,21 +284,26 @@ class BibleMediaItem(MediaManagerItem):
self.advancedSecondComboBox.setVisible(False) self.advancedSecondComboBox.setVisible(False)
self.quickSecondLabel.setVisible(False) self.quickSecondLabel.setVisible(False)
self.quickSecondComboBox.setVisible(False) self.quickSecondComboBox.setVisible(False)
self.quickLayoutComboBox.setCurrentIndex(self.settings.layout_style) self.quickStyleComboBox.setCurrentIndex(self.settings.layout_style)
self.advancedStyleComboBox.setCurrentIndex(self.settings.layout_style)
def retranslateUi(self): def retranslateUi(self):
log.debug(u'retranslateUi') log.debug(u'retranslateUi')
self.quickSearchLabel.setText(
translate('BiblesPlugin.MediaItem', 'Find:'))
self.quickVersionLabel.setText(u'%s:' % UiStrings().Version) self.quickVersionLabel.setText(u'%s:' % UiStrings().Version)
self.quickSecondLabel.setText( self.quickSecondLabel.setText(
translate('BiblesPlugin.MediaItem', 'Second:')) translate('BiblesPlugin.MediaItem', 'Second:'))
self.quickSearchLabel.setText( self.quickStyleLabel.setText(UiStrings().LayoutStyle)
translate('BiblesPlugin.MediaItem', 'Find:')) self.quickStyleComboBox.setItemText(LayoutStyle.VersePerSlide,
self.quickSearchButton.setText(UiStrings().Search) UiStrings().VersePerSlide)
self.quickStyleComboBox.setItemText(LayoutStyle.VersePerLine,
UiStrings().VersePerLine)
self.quickStyleComboBox.setItemText(LayoutStyle.Continuous,
UiStrings().Continuous)
self.quickLockButton.setToolTip(translate('BiblesPlugin.MediaItem', self.quickLockButton.setToolTip(translate('BiblesPlugin.MediaItem',
'Toggle to keep or clear the previous results.')) 'Toggle to keep or clear the previous results.'))
self.advancedVersionLabel.setText(u'%s:' % UiStrings().Version) self.quickSearchButton.setText(UiStrings().Search)
self.advancedSecondLabel.setText(
translate('BiblesPlugin.MediaItem', 'Second:'))
self.advancedBookLabel.setText( self.advancedBookLabel.setText(
translate('BiblesPlugin.MediaItem', 'Book:')) translate('BiblesPlugin.MediaItem', 'Book:'))
self.advancedChapterLabel.setText( self.advancedChapterLabel.setText(
@ -272,16 +314,19 @@ class BibleMediaItem(MediaManagerItem):
translate('BiblesPlugin.MediaItem', 'From:')) translate('BiblesPlugin.MediaItem', 'From:'))
self.advancedToLabel.setText( self.advancedToLabel.setText(
translate('BiblesPlugin.MediaItem', 'To:')) translate('BiblesPlugin.MediaItem', 'To:'))
self.advancedSearchButton.setText(UiStrings().Search) self.advancedVersionLabel.setText(u'%s:' % UiStrings().Version)
self.advancedSecondLabel.setText(
translate('BiblesPlugin.MediaItem', 'Second:'))
self.advancedStyleLabel.setText(UiStrings().LayoutStyle)
self.advancedStyleComboBox.setItemText(LayoutStyle.VersePerSlide,
UiStrings().VersePerSlide)
self.advancedStyleComboBox.setItemText(LayoutStyle.VersePerLine,
UiStrings().VersePerLine)
self.advancedStyleComboBox.setItemText(LayoutStyle.Continuous,
UiStrings().Continuous)
self.advancedLockButton.setToolTip(translate('BiblesPlugin.MediaItem', self.advancedLockButton.setToolTip(translate('BiblesPlugin.MediaItem',
'Toggle to keep or clear the previous results.')) 'Toggle to keep or clear the previous results.'))
self.quickLayoutLabel.setText(UiStrings().LayoutStyle) self.advancedSearchButton.setText(UiStrings().Search)
self.quickLayoutComboBox.setItemText(LayoutStyle.VersePerSlide,
UiStrings().VersePerSlide)
self.quickLayoutComboBox.setItemText(LayoutStyle.VersePerLine,
UiStrings().VersePerLine)
self.quickLayoutComboBox.setItemText(LayoutStyle.Continuous,
UiStrings().Continuous)
def initialise(self): def initialise(self):
log.debug(u'bible manager initialise') log.debug(u'bible manager initialise')
@ -303,28 +348,6 @@ class BibleMediaItem(MediaManagerItem):
self.configUpdated() self.configUpdated()
log.debug(u'bible manager initialise complete') log.debug(u'bible manager initialise complete')
def onImportClick(self):
if not hasattr(self, u'import_wizard'):
self.import_wizard = BibleImportForm(self, self.parent.manager,
self.parent)
# If the import was not cancelled then reload.
if self.import_wizard.exec_():
self.reloadBibles()
def onSearchTabBarCurrentChanged(self, index):
if index == 0:
self.advancedTab.setVisible(False)
self.quickTab.setVisible(True)
else:
self.quickTab.setVisible(False)
self.advancedTab.setVisible(True)
def onLockButtonToggled(self, checked):
if checked:
self.sender().setIcon(self.lockIcon)
else:
self.sender().setIcon(self.unlockIcon)
def loadBibles(self): def loadBibles(self):
log.debug(u'Loading Bibles') log.debug(u'Loading Bibles')
self.quickVersionComboBox.clear() self.quickVersionComboBox.clear()
@ -422,6 +445,47 @@ class BibleMediaItem(MediaManagerItem):
books.sort() books.sort()
add_widget_completer(books, self.quickSearchEdit) add_widget_completer(books, self.quickSearchEdit)
def onImportClick(self):
if not hasattr(self, u'import_wizard'):
self.import_wizard = BibleImportForm(self, self.parent.manager,
self.parent)
# If the import was not cancelled then reload.
if self.import_wizard.exec_():
self.reloadBibles()
def onSearchTabBarCurrentChanged(self, index):
if index == 0:
self.advancedTab.setVisible(False)
self.quickTab.setVisible(True)
self.quickSearchEdit.setFocus()
else:
self.quickTab.setVisible(False)
self.advancedTab.setVisible(True)
def onLockButtonToggled(self, checked):
if checked:
self.sender().setIcon(self.lockIcon)
else:
self.sender().setIcon(self.unlockIcon)
def onQuickStyleComboBoxChanged(self):
self.settings.layout_style = self.quickStyleComboBox.currentIndex()
self.advancedStyleComboBox.setCurrentIndex(self.settings.layout_style)
self.settings.layoutStyleComboBox.setCurrentIndex(
self.settings.layout_style)
QtCore.QSettings().setValue(
self.settingsSection + u'/verse layout style',
QtCore.QVariant(self.settings.layout_style))
def onAdvancedStyleComboBoxChanged(self):
self.settings.layout_style = self.advancedStyleComboBox.currentIndex()
self.quickStyleComboBox.setCurrentIndex(self.settings.layout_style)
self.settings.layoutStyleComboBox.setCurrentIndex(
self.settings.layout_style)
QtCore.QSettings().setValue(
self.settingsSection + u'/verse layout style',
QtCore.QVariant(self.settings.layout_style))
def onAdvancedVersionComboBox(self): def onAdvancedVersionComboBox(self):
QtCore.QSettings().setValue(self.settingsSection + u'/advanced bible', QtCore.QSettings().setValue(self.settingsSection + u'/advanced bible',
QtCore.QVariant(self.advancedVersionComboBox.currentText())) QtCore.QVariant(self.advancedVersionComboBox.currentText()))
@ -537,7 +601,7 @@ class BibleMediaItem(MediaManagerItem):
elif self.search_results: elif self.search_results:
self.displayResults(bible, second_bible) self.displayResults(bible, second_bible)
self.advancedSearchButton.setEnabled(True) self.advancedSearchButton.setEnabled(True)
check_search_result(self.listView, self.search_results) self.check_search_result()
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
@ -578,35 +642,24 @@ class BibleMediaItem(MediaManagerItem):
elif self.search_results: elif self.search_results:
self.displayResults(bible, second_bible) self.displayResults(bible, second_bible)
self.quickSearchButton.setEnabled(True) self.quickSearchButton.setEnabled(True)
check_search_result(self.listView, self.search_results) self.check_search_result()
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
def __checkSecondBible(self, bible, second_bible):
"""
Check if the first item is a second bible item or not.
"""
bitem = self.listView.item(0)
if not bitem.flags() & QtCore.Qt.ItemIsSelectable:
# The item is the "No Search Results" item.
self.listView.clear()
self.displayResults(bible, second_bible)
return
else:
item_second_bible = self._decodeQtObject(bitem, 'second_bible')
if item_second_bible and second_bible or not item_second_bible and \
not second_bible:
self.displayResults(bible, second_bible)
elif critical_error_message_box(
message=translate('BiblePlugin.MediaItem',
'You cannot combine single and dual Bible verse search results. '
'Do you want to delete your search results and start a new '
'search?'),
parent=self, question=True) == QtGui.QMessageBox.Yes:
self.listView.clear()
self.displayResults(bible, second_bible)
def displayResults(self, bible, second_bible=u''): 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 Displays the search results in the media manager. All data needed for
further action is saved for/in each row. further action is saved for/in each row.
@ -626,7 +679,8 @@ class BibleMediaItem(MediaManagerItem):
second_bible, u'Copyright').value second_bible, u'Copyright').value
second_permissions = self.parent.manager.get_meta_data( second_permissions = self.parent.manager.get_meta_data(
second_bible, u'Permissions').value second_bible, u'Permissions').value
for count, verse in enumerate(self.search_results): items = []
for count, verse in enumerate(search_results):
data = { data = {
'book': QtCore.QVariant(verse.book.name), 'book': QtCore.QVariant(verse.book.name),
'chapter': QtCore.QVariant(verse.chapter), 'chapter': QtCore.QVariant(verse.chapter),
@ -658,19 +712,8 @@ class BibleMediaItem(MediaManagerItem):
verse.chapter, verse_separator, verse.verse, version) verse.chapter, verse_separator, verse.verse, version)
bible_verse = QtGui.QListWidgetItem(bible_text) bible_verse = QtGui.QListWidgetItem(bible_text)
bible_verse.setData(QtCore.Qt.UserRole, QtCore.QVariant(data)) bible_verse.setData(QtCore.Qt.UserRole, QtCore.QVariant(data))
self.listView.addItem(bible_verse) items.append(bible_verse)
self.listView.selectAll() return items
self.search_results = {}
self.second_search_results = {}
def _decodeQtObject(self, bitem, key):
reference = bitem.data(QtCore.Qt.UserRole)
if isinstance(reference, QtCore.QVariant):
reference = reference.toPyObject()
obj = reference[QtCore.QString(key)]
if isinstance(obj, QtCore.QVariant):
obj = obj.toPyObject()
return unicode(obj).strip()
def generateSlideData(self, service_item, item=None, xmlVersion=False): def generateSlideData(self, service_item, item=None, xmlVersion=False):
""" """
@ -678,7 +721,10 @@ class BibleMediaItem(MediaManagerItem):
service item's title. service item's title.
""" """
log.debug(u'generating slide data') log.debug(u'generating slide data')
items = self.listView.selectedIndexes() if item:
items = item
else:
items = self.listView.selectedItems()
if len(items) == 0: if len(items) == 0:
return False return False
bible_text = u'' bible_text = u''
@ -687,8 +733,7 @@ class BibleMediaItem(MediaManagerItem):
raw_slides = [] raw_slides = []
raw_title = [] raw_title = []
verses = VerseReferenceList() verses = VerseReferenceList()
for item in items: for bitem in items:
bitem = self.listView.item(item.row())
book = self._decodeQtObject(bitem, 'book') book = self._decodeQtObject(bitem, 'book')
chapter = int(self._decodeQtObject(bitem, 'chapter')) chapter = int(self._decodeQtObject(bitem, 'chapter'))
verse = int(self._decodeQtObject(bitem, 'verse')) verse = int(self._decodeQtObject(bitem, 'verse'))
@ -722,11 +767,11 @@ class BibleMediaItem(MediaManagerItem):
else: else:
bible_text = u'%s %s&nbsp;%s\n' % (bible_text, verse_text, text) bible_text = u'%s %s&nbsp;%s\n' % (bible_text, verse_text, text)
if not old_item: if not old_item:
start_item = item start_item = bitem
elif self.checkTitle(item, old_item): elif self.checkTitle(bitem, old_item):
raw_title.append(self.formatTitle(start_item, old_item)) raw_title.append(self.formatTitle(start_item, old_item))
start_item = item start_item = bitem
old_item = item old_item = bitem
old_chapter = chapter old_chapter = chapter
# Add footer # Add footer
service_item.raw_footer.append(verses.format_verses()) service_item.raw_footer.append(verses.format_verses())
@ -734,7 +779,7 @@ class BibleMediaItem(MediaManagerItem):
verses.add_version(second_version, second_copyright, verses.add_version(second_version, second_copyright,
second_permissions) second_permissions)
service_item.raw_footer.append(verses.format_versions()) 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 there are no more items we check whether we have to add bible_text.
if bible_text: if bible_text:
raw_slides.append(bible_text.lstrip()) raw_slides.append(bible_text.lstrip())
@ -757,9 +802,9 @@ class BibleMediaItem(MediaManagerItem):
[service_item.add_from_text(slide[:30], slide) for slide in raw_slides] [service_item.add_from_text(slide[:30], slide) for slide in raw_slides]
return True 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 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. Genesis 1:1-6 as well as Daniel 2:14.
@ -771,10 +816,8 @@ class BibleMediaItem(MediaManagerItem):
""" """
verse_separator = get_reference_match(u'sep_v_display') verse_separator = get_reference_match(u'sep_v_display')
range_separator = get_reference_match(u'sep_r_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_chapter = self._decodeQtObject(old_bitem, 'chapter')
old_verse = self._decodeQtObject(old_bitem, 'verse') old_verse = self._decodeQtObject(old_bitem, 'verse')
start_bitem = self.listView.item(start_item.row())
start_book = self._decodeQtObject(start_bitem, 'book') start_book = self._decodeQtObject(start_bitem, 'book')
start_chapter = self._decodeQtObject(start_bitem, 'chapter') start_chapter = self._decodeQtObject(start_bitem, 'chapter')
start_verse = self._decodeQtObject(start_bitem, 'verse') start_verse = self._decodeQtObject(start_bitem, 'verse')
@ -795,9 +838,9 @@ class BibleMediaItem(MediaManagerItem):
range_separator + old_chapter + verse_separator + old_verse range_separator + old_chapter + verse_separator + old_verse
return u'%s %s (%s)' % (start_book, verse_range, bibles) 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 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. Genesis 1:1-6, but the next verse is Daniel 2:14, we return True.
@ -808,13 +851,11 @@ class BibleMediaItem(MediaManagerItem):
The item we were previously dealing with. The item we were previously dealing with.
""" """
# Get all the necessary meta data. # Get all the necessary meta data.
bitem = self.listView.item(item.row())
book = self._decodeQtObject(bitem, 'book') book = self._decodeQtObject(bitem, 'book')
chapter = int(self._decodeQtObject(bitem, 'chapter')) chapter = int(self._decodeQtObject(bitem, 'chapter'))
verse = int(self._decodeQtObject(bitem, 'verse')) verse = int(self._decodeQtObject(bitem, 'verse'))
bible = self._decodeQtObject(bitem, 'bible') bible = self._decodeQtObject(bitem, 'bible')
second_bible = self._decodeQtObject(bitem, 'second_bible') second_bible = self._decodeQtObject(bitem, 'second_bible')
old_bitem = self.listView.item(old_item.row())
old_book = self._decodeQtObject(old_bitem, 'book') old_book = self._decodeQtObject(old_bitem, 'book')
old_chapter = int(self._decodeQtObject(old_bitem, 'chapter')) old_chapter = int(self._decodeQtObject(old_bitem, 'chapter'))
old_verse = int(self._decodeQtObject(old_bitem, 'verse')) old_verse = int(self._decodeQtObject(old_bitem, 'verse'))
@ -867,10 +908,21 @@ class BibleMediaItem(MediaManagerItem):
return u'{su}[%s]{/su}' % verse_text return u'{su}[%s]{/su}' % verse_text
return u'{su}%s{/su}' % verse_text return u'{su}%s{/su}' % verse_text
def onLayoutStyleComboBoxChanged(self): def search(self, string):
self.settings.layout_style = self.quickLayoutComboBox.currentIndex() """
self.settings.layoutStyleComboBox.setCurrentIndex( Search for some Bible verses (by reference).
self.settings.layout_style) """
QtCore.QSettings().setValue( bible = unicode(self.quickVersionComboBox.currentText())
self.settingsSection + u'/verse layout style', search_results = self.parent.manager.get_verses(bible, string, False)
QtCore.QVariant(self.settings.layout_style)) 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

View File

@ -27,6 +27,7 @@
import logging import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from sqlalchemy.sql import or_, func
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
check_item_selected check_item_selected
@ -47,6 +48,7 @@ class CustomMediaItem(MediaManagerItem):
MediaManagerItem.__init__(self, parent, self, icon) MediaManagerItem.__init__(self, parent, self, icon)
self.singleServiceItem = False self.singleServiceItem = False
self.quickPreviewAllowed = True self.quickPreviewAllowed = True
self.hasSearch = True
# Holds information about whether the edit is remotly triggered and # Holds information about whether the edit is remotly triggered and
# which Custom is required. # which Custom is required.
self.remoteCustom = -1 self.remoteCustom = -1
@ -162,3 +164,15 @@ class CustomMediaItem(MediaManagerItem):
raw_footer.append(u'') raw_footer.append(u'')
service_item.raw_footer = raw_footer service_item.raw_footer = raw_footer
return True 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

View File

@ -47,6 +47,7 @@ class ImageMediaItem(MediaManagerItem):
self.IconPath = u'images/image' self.IconPath = u'images/image'
MediaManagerItem.__init__(self, parent, self, icon) MediaManagerItem.__init__(self, parent, self, icon)
self.quickPreviewAllowed = True self.quickPreviewAllowed = True
self.hasSearch = True
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged) QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged)
@ -130,8 +131,12 @@ class ImageMediaItem(MediaManagerItem):
self.parent.formparent.finishedProgressBar() self.parent.formparent.finishedProgressBar()
def generateSlideData(self, service_item, item=None, xmlVersion=False): def generateSlideData(self, service_item, item=None, xmlVersion=False):
items = self.listView.selectedIndexes() if item:
if items: items = [item]
else:
items = self.listView.selectedItems()
if not items:
return False
service_item.title = unicode(self.plugin.nameStrings[u'plural']) service_item.title = unicode(self.plugin.nameStrings[u'plural'])
service_item.add_capability(ItemCapabilities.AllowsMaintain) service_item.add_capability(ItemCapabilities.AllowsMaintain)
service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsPreview)
@ -141,8 +146,7 @@ class ImageMediaItem(MediaManagerItem):
service_item.theme = -1 service_item.theme = -1
missing_items = [] missing_items = []
missing_items_filenames = [] missing_items_filenames = []
for item in items: for bitem in items:
bitem = self.listView.item(item.row())
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
if not os.path.exists(filename): if not os.path.exists(filename):
missing_items.append(item) missing_items.append(item)
@ -167,14 +171,11 @@ class ImageMediaItem(MediaManagerItem):
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No: QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
return False return False
# Continue with the existing images. # Continue with the existing images.
for item in items: for bitem in items:
bitem = self.listView.item(item.row())
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
(path, name) = os.path.split(filename) (path, name) = os.path.split(filename)
service_item.add_from_image(filename, name) service_item.add_from_image(filename, name)
return True return True
else:
return False
def onResetClick(self): def onResetClick(self):
""" """
@ -208,3 +209,14 @@ class ImageMediaItem(MediaManagerItem):
unicode(translate('ImagePlugin.MediaItem', unicode(translate('ImagePlugin.MediaItem',
'There was a problem replacing your background, ' 'There was a problem replacing your background, '
'the image file "%s" no longer exists.')) % filename) '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

View File

@ -50,6 +50,7 @@ class MediaMediaItem(MediaManagerItem):
u':/media/media_video.png').toImage() u':/media/media_video.png').toImage()
MediaManagerItem.__init__(self, parent, self, icon) MediaManagerItem.__init__(self, parent, self, icon)
self.singleServiceItem = False self.singleServiceItem = False
self.hasSearch = True
self.mediaObject = None self.mediaObject = None
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'video_background_replaced'), QtCore.SIGNAL(u'video_background_replaced'),
@ -212,3 +213,14 @@ class MediaMediaItem(MediaManagerItem):
log.debug(u'CreatePhonon') log.debug(u'CreatePhonon')
if not self.mediaObject: if not self.mediaObject:
self.mediaObject = Phonon.MediaObject(self) 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

View File

@ -53,6 +53,7 @@ class PresentationMediaItem(MediaManagerItem):
self.Automatic = u'' self.Automatic = u''
MediaManagerItem.__init__(self, parent, self, icon) MediaManagerItem.__init__(self, parent, self, icon)
self.message_listener = MessageListener(self) self.message_listener = MessageListener(self)
self.hasSearch = True
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild) QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)
@ -231,7 +232,10 @@ class PresentationMediaItem(MediaManagerItem):
in the slidecontroller. In the case of powerpoints, an image in the slidecontroller. In the case of powerpoints, an image
for each slide for each slide
""" """
items = self.listView.selectedIndexes() if item:
items = [item]
else:
items = self.listView.selectedItems()
if len(items) > 1: if len(items) > 1:
return False return False
service_item.title = unicode(self.displayTypeComboBox.currentText()) service_item.title = unicode(self.displayTypeComboBox.currentText())
@ -240,8 +244,7 @@ class PresentationMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.AllowsDetailedTitleDisplay) service_item.add_capability(ItemCapabilities.AllowsDetailedTitleDisplay)
shortname = service_item.shortname shortname = service_item.shortname
if shortname: if shortname:
for item in items: for bitem in items:
bitem = self.listView.item(item.row())
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
if os.path.exists(filename): if os.path.exists(filename):
if shortname == self.Automatic: if shortname == self.Automatic:
@ -303,3 +306,12 @@ class PresentationMediaItem(MediaManagerItem):
if filetype in self.controllers[controller].alsosupports: if filetype in self.controllers[controller].alsosupports:
return controller return controller
return None 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

View File

@ -43,6 +43,7 @@
<a href="#service-manager" data-role="button" data-icon="arrow-r" data-iconpos="right">Service Manager</a> <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="#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="#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> </div>
</div> </div>
@ -50,6 +51,7 @@
<div data-role="header"> <div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a> <a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Service Manager</h1> <h1>Service Manager</h1>
<a href="#" id="service-refresh" data-role="button" data-icon="refresh">Refresh</a>
</div> </div>
<div data-role="content"> <div data-role="content">
<ul data-role="listview" data-inset="true"> <ul data-role="listview" data-inset="true">
@ -57,9 +59,8 @@
</div> </div>
<div data-role="footer" data-theme="b" class="ui-bar"> <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-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-unblank" data-role="button" data-icon="unblank">Show</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">Prev</a>
<a href="#" id="service-previous" data-role="button" data-icon="arrow-l">Previous</a>
<a href="#" id="service-next" data-role="button" data-icon="arrow-r" data-iconpos="right">Next</a> <a href="#" id="service-next" data-role="button" data-icon="arrow-r" data-iconpos="right">Next</a>
</div> </div>
</div> </div>
@ -67,6 +68,7 @@
<div data-role="header"> <div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a> <a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Slide Controller</h1> <h1>Slide Controller</h1>
<a href="#" id="controller-refresh" data-role="button" data-icon="refresh">Refresh</a>
</div> </div>
<div data-role="content"> <div data-role="content">
<ul data-role="listview" data-inset="true"> <ul data-role="listview" data-inset="true">
@ -74,9 +76,8 @@
</div> </div>
<div data-role="footer" data-theme="b" class="ui-bar"> <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-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-unblank" data-role="button" data-icon="unblank">Show</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">Prev</a>
<a href="#" id="controller-previous" data-role="button" data-icon="arrow-l">Previous</a>
<a href="#" id="controller-next" data-role="button" data-icon="arrow-r" data-iconpos="right">Next</a> <a href="#" id="controller-next" data-role="button" data-icon="arrow-r" data-iconpos="right">Next</a>
</div> </div>
</div> </div>
@ -93,5 +94,23 @@
<a href="#" id="alert-submit" data-role="button">Show Alert</a> <a href="#" id="alert-submit" data-role="button">Show Alert</a>
</div> </div>
</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> </body>
</html> </html>

View File

@ -39,6 +39,19 @@ window.OpenLP = {
} }
return $(targ); 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) { loadService: function (event) {
$.getJSON( $.getJSON(
"/api/service/list", "/api/service/list",
@ -63,7 +76,9 @@ window.OpenLP = {
var ul = $("#slide-controller > div[data-role=content] > ul[data-role=listview]"); var ul = $("#slide-controller > div[data-role=content] > ul[data-role=listview]");
ul.html(""); ul.html("");
for (idx in data.results.slides) { 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 />'); text = text.replace(/\n/g, '<br />');
var li = $("<li data-icon=\"false\">").append( var li = $("<li data-icon=\"false\">").append(
$("<a href=\"#\">").attr("value", parseInt(idx, 10)).html(text)); $("<a href=\"#\">").attr("value", parseInt(idx, 10)).html(text));
@ -189,7 +204,43 @@ window.OpenLP = {
} }
); );
return false; 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
$("#service-manager").live("pagebeforeshow", OpenLP.loadService); $("#service-manager").live("pagebeforeshow", OpenLP.loadService);
@ -207,7 +258,10 @@ $("#controller-blank").live("click", OpenLP.blankDisplay);
$("#controller-unblank").live("click", OpenLP.unblankDisplay); $("#controller-unblank").live("click", OpenLP.unblankDisplay);
// Alerts // Alerts
$("#alert-submit").live("click", OpenLP.showAlert); $("#alert-submit").live("click", OpenLP.showAlert);
// Search
$("#search-submit").live("click", OpenLP.search);
// Poll the server twice a second to get any updates. // Poll the server twice a second to get any updates.
OpenLP.getSearchablePlugins();
$.ajaxSetup({ cache: false }); $.ajaxSetup({ cache: false });
setInterval("OpenLP.pollServer();", 500); setInterval("OpenLP.pollServer();", 500);
OpenLP.pollServer(); OpenLP.pollServer();

View File

@ -26,7 +26,7 @@
--> -->
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>OpenLP 2.0 Remote</title> <title>OpenLP 2.0 Stage View</title>
<link rel="stylesheet" href="/files/stage.css" /> <link rel="stylesheet" href="/files/stage.css" />
<script type="text/javascript" src="/files/jquery.js"></script> <script type="text/javascript" src="/files/jquery.js"></script>
<script type="text/javascript" src="/files/stage.js"></script> <script type="text/javascript" src="/files/stage.js"></script>

View File

@ -123,7 +123,7 @@ except ImportError:
from PyQt4 import QtCore, QtNetwork 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.ui import HideMode
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
@ -250,7 +250,10 @@ class HttpConnection(object):
(r'^/api/controller/(live|preview)/(.*)$', self.controller), (r'^/api/controller/(live|preview)/(.*)$', self.controller),
(r'^/api/service/(.*)$', self.service), (r'^/api/service/(.*)$', self.service),
(r'^/api/display/(hide|show)$', self.display), (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()'), QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'readyRead()'),
self.ready_read) self.ready_read)
@ -409,8 +412,8 @@ class HttpConnection(object):
item[u'html'] = unicode(frame[u'html']) item[u'html'] = unicode(frame[u'html'])
else: else:
item[u'tag'] = unicode(index + 1) item[u'tag'] = unicode(index + 1)
item[u'text'] = u'' item[u'text'] = unicode(frame[u'title'])
item[u'html'] = u'' item[u'html'] = unicode(frame[u'title'])
item[u'selected'] = (self.parent.current_slide == index) item[u'selected'] = (self.parent.current_slide == index)
data.append(item) data.append(item)
json_data = {u'results': {u'slides': data}} json_data = {u'results': {u'slides': data}}
@ -443,6 +446,50 @@ class HttpConnection(object):
return HttpResponse(json.dumps({u'results': {u'success': True}}), return HttpResponse(json.dumps({u'results': {u'success': True}}),
{u'Content-Type': u'application/json'}) {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): def send_response(self, response):
http = u'HTTP/1.1 %s\r\n' % response.code http = u'HTTP/1.1 %s\r\n' % response.code
for header, value in response.headers.iteritems(): for header, value in response.headers.iteritems():

View File

@ -32,7 +32,7 @@ from PyQt4 import QtCore, QtGui
from sqlalchemy.sql import or_ from sqlalchemy.sql import or_
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
translate, check_item_selected, PluginStatus, check_search_result translate, check_item_selected, PluginStatus
from openlp.core.lib.searchedit import SearchEdit 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, \
@ -74,6 +74,7 @@ class SongMediaItem(MediaManagerItem):
self.editItem = None self.editItem = None
self.whitespace = re.compile(r'\W+', re.UNICODE) self.whitespace = re.compile(r'\W+', re.UNICODE)
self.quickPreviewAllowed = True self.quickPreviewAllowed = True
self.hasSearch = True
def addEndHeaderBar(self): def addEndHeaderBar(self):
self.addToolbarSeparator() self.addToolbarSeparator()
@ -171,11 +172,7 @@ class SongMediaItem(MediaManagerItem):
search_type = self.searchTextEdit.currentSearchType() search_type = self.searchTextEdit.currentSearchType()
if search_type == SongSearch.Entire: if search_type == SongSearch.Entire:
log.debug(u'Entire Song Search') log.debug(u'Entire Song Search')
search_results = self.parent.manager.get_all_objects(Song, search_results = self.searchEntire(search_keywords)
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'%')))
self.displayResultsSong(search_results) self.displayResultsSong(search_results)
elif search_type == SongSearch.Titles: elif search_type == SongSearch.Titles:
log.debug(u'Titles Search') log.debug(u'Titles Search')
@ -199,7 +196,14 @@ class SongMediaItem(MediaManagerItem):
search_results = self.parent.manager.get_all_objects(Song, search_results = self.parent.manager.get_all_objects(Song,
Song.theme_name == search_keywords) Song.theme_name == search_keywords)
self.displayResultsSong(search_results) self.displayResultsSong(search_results)
check_search_result(self.listView, 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): def onSongListLoad(self):
""" """
@ -217,7 +221,8 @@ class SongMediaItem(MediaManagerItem):
# Push edits to the service manager to update items # Push edits to the service manager to update items
if self.editItem and self.updateServiceOnEdit and \ if self.editItem and self.updateServiceOnEdit and \
not self.remoteTriggered: not self.remoteTriggered:
item = self.buildServiceItem(self.editItem) item_id = _getIdOfItemToGenerate(self.editItem)
item = self.buildServiceItem(item_id)
self.parent.serviceManager.replaceServiceItem(item) self.parent.serviceManager.replaceServiceItem(item)
self.onRemoteEditClear() self.onRemoteEditClear()
self.onSearchTextButtonClick() self.onSearchTextButtonClick()
@ -475,3 +480,13 @@ class SongMediaItem(MediaManagerItem):
""" """
return locale.strcoll(unicode(song_1.title.lower()), return locale.strcoll(unicode(song_1.title.lower()),
unicode(song_2.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

View File

@ -268,4 +268,3 @@ class SongsPlugin(Plugin):
action_list.remove_action(self.songExportItem, UiStrings().Export) action_list.remove_action(self.songExportItem, UiStrings().Export)
action_list.remove_action(self.toolsReindexItem, UiStrings().Tools) action_list.remove_action(self.toolsReindexItem, UiStrings().Tools)
Plugin.finalise(self) Plugin.finalise(self)