forked from openlp/openlp
Sync
This commit is contained in:
commit
d39ecb8e8e
@ -85,10 +85,13 @@ class OpenLP(QtGui.QApplication):
|
|||||||
QtGui.QApplication.exec_()
|
QtGui.QApplication.exec_()
|
||||||
self.sharedMemory.detach()
|
self.sharedMemory.detach()
|
||||||
|
|
||||||
def run(self):
|
def run(self, args):
|
||||||
"""
|
"""
|
||||||
Run the OpenLP application.
|
Run the OpenLP application.
|
||||||
"""
|
"""
|
||||||
|
# On Windows, the args passed into the constructor are
|
||||||
|
# ignored. Not very handy, so set the ones we want to use.
|
||||||
|
self.args = args
|
||||||
# provide a listener for widgets to reqest a screen update.
|
# provide a listener for widgets to reqest a screen update.
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
|
QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
|
||||||
@ -115,7 +118,7 @@ class OpenLP(QtGui.QApplication):
|
|||||||
# make sure Qt really display the splash screen
|
# make sure Qt really display the splash screen
|
||||||
self.processEvents()
|
self.processEvents()
|
||||||
# start the main app window
|
# start the main app window
|
||||||
self.mainWindow = MainWindow(self.clipboard(), self.arguments())
|
self.mainWindow = MainWindow(self.clipboard(), self.args)
|
||||||
self.mainWindow.show()
|
self.mainWindow.show()
|
||||||
if show_splash:
|
if show_splash:
|
||||||
# now kill the splashscreen
|
# now kill the splashscreen
|
||||||
@ -250,7 +253,7 @@ def main():
|
|||||||
log.debug(u'Could not find default_translator.')
|
log.debug(u'Could not find default_translator.')
|
||||||
if not options.no_error_form:
|
if not options.no_error_form:
|
||||||
sys.excepthook = app.hookException
|
sys.excepthook = app.hookException
|
||||||
sys.exit(app.run())
|
sys.exit(app.run(qt_args))
|
||||||
|
|
||||||
if __name__ == u'__main__':
|
if __name__ == u'__main__':
|
||||||
"""
|
"""
|
||||||
|
@ -28,6 +28,7 @@ Provides the generic functions for interfacing plugins with the Media Manager.
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
@ -90,6 +91,7 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
"""
|
"""
|
||||||
QtGui.QWidget.__init__(self)
|
QtGui.QWidget.__init__(self)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
self.whitespace = re.compile(r'\W+', re.UNICODE)
|
||||||
#TODO: plugin should not be the parent in future
|
#TODO: plugin should not be the parent in future
|
||||||
self.plugin = parent # plugin
|
self.plugin = parent # plugin
|
||||||
visible_title = self.plugin.getString(StringContent.VisibleName)
|
visible_title = self.plugin.getString(StringContent.VisibleName)
|
||||||
@ -102,16 +104,21 @@ 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)
|
||||||
self.requiredIcons()
|
self.requiredIcons()
|
||||||
self.setupUi()
|
self.setupUi()
|
||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
|
self.autoSelectItem = None
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'%s_service_load' % self.parent.name.lower()),
|
QtCore.SIGNAL(u'%s_service_load' % self.parent.name.lower()),
|
||||||
self.serviceLoad)
|
self.serviceLoad)
|
||||||
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
|
QtCore.SIGNAL(u'%s_set_autoselect_item' % self.parent.name.lower()),
|
||||||
|
self.setAutoSelectItem)
|
||||||
|
|
||||||
def requiredIcons(self):
|
def requiredIcons(self):
|
||||||
"""
|
"""
|
||||||
This method is called to define the icons for the plugin.
|
This method is called to define the icons for the plugin.
|
||||||
@ -464,6 +471,9 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
if keepFocus:
|
if keepFocus:
|
||||||
self.listView.setFocus()
|
self.listView.setFocus()
|
||||||
|
|
||||||
|
def setAutoSelectItem(self, itemToSelect=None):
|
||||||
|
self.autoSelectItem = itemToSelect
|
||||||
|
|
||||||
def onLiveClick(self):
|
def onLiveClick(self):
|
||||||
"""
|
"""
|
||||||
Send an item live by building a service item then adding that service
|
Send an item live by building a service item then adding that service
|
||||||
@ -474,11 +484,23 @@ 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:
|
||||||
log.debug(u'%s Live requested', self.plugin.name)
|
self.goLive()
|
||||||
serviceItem = self.buildServiceItem()
|
|
||||||
if serviceItem:
|
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
|
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):
|
||||||
"""
|
"""
|
||||||
@ -487,24 +509,24 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
if not self.listView.selectedIndexes() and not self.remoteTriggered:
|
if not self.listView.selectedIndexes() and not self.remoteTriggered:
|
||||||
QtGui.QMessageBox.information(self, UiStrings().NISp,
|
QtGui.QMessageBox.information(self, UiStrings().NISp,
|
||||||
translate('OpenLP.MediaManagerItem',
|
translate('OpenLP.MediaManagerItem',
|
||||||
'You must select one or more items.'))
|
'You must select one or more items to add.'))
|
||||||
else:
|
else:
|
||||||
# Is it posssible to process multiple list items to generate
|
# Is it posssible to process multiple list items to generate
|
||||||
# multiple service items?
|
# multiple service items?
|
||||||
if self.singleServiceItem or self.remoteTriggered:
|
if self.singleServiceItem or self.remoteTriggered:
|
||||||
log.debug(u'%s Add requested', self.plugin.name)
|
log.debug(u'%s Add requested', self.plugin.name)
|
||||||
serviceItem = self.buildServiceItem(None, True)
|
self.addToService(replace=self.remoteTriggered)
|
||||||
if serviceItem:
|
|
||||||
serviceItem.from_plugin = False
|
|
||||||
self.parent.serviceManager.addServiceItem(serviceItem,
|
|
||||||
replace=self.remoteTriggered)
|
|
||||||
else:
|
else:
|
||||||
items = self.listView.selectedIndexes()
|
items = self.listView.selectedIndexes()
|
||||||
for item in items:
|
for item in items:
|
||||||
serviceItem = self.buildServiceItem(item, True)
|
self.addToService(item)
|
||||||
if serviceItem:
|
|
||||||
serviceItem.from_plugin = False
|
def addToService(self, item=None, replace=None):
|
||||||
self.parent.serviceManager.addServiceItem(serviceItem)
|
serviceItem = self.buildServiceItem(item, True)
|
||||||
|
if serviceItem:
|
||||||
|
serviceItem.from_plugin = False
|
||||||
|
self.parent.serviceManager.addServiceItem(serviceItem,
|
||||||
|
replace=replace)
|
||||||
|
|
||||||
def onAddEditClick(self):
|
def onAddEditClick(self):
|
||||||
"""
|
"""
|
||||||
@ -586,3 +608,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')
|
||||||
|
@ -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
|
||||||
|
@ -300,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))
|
||||||
|
@ -207,6 +207,8 @@ class ThemeXML(object):
|
|||||||
"""
|
"""
|
||||||
A class to encapsulate the Theme XML.
|
A class to encapsulate the Theme XML.
|
||||||
"""
|
"""
|
||||||
|
FIRST_CAMEL_REGEX = re.compile(u'(.)([A-Z][a-z]+)')
|
||||||
|
SECOND_CAMEL_REGEX = re.compile(u'([a-z0-9])([A-Z])')
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
Initialise the theme object.
|
Initialise the theme object.
|
||||||
@ -581,8 +583,8 @@ class ThemeXML(object):
|
|||||||
"""
|
"""
|
||||||
Change Camel Case string to python string
|
Change Camel Case string to python string
|
||||||
"""
|
"""
|
||||||
sub_name = re.sub(u'(.)([A-Z][a-z]+)', r'\1_\2', name)
|
sub_name = ThemeXML.FIRST_CAMEL_REGEX.sub(r'\1_\2', name)
|
||||||
return re.sub(u'([a-z0-9])([A-Z])', r'\1_\2', sub_name).lower()
|
return ThemeXML.SECOND_CAMEL_REGEX.sub(r'\1_\2', sub_name).lower()
|
||||||
|
|
||||||
def _build_xml_from_attrs(self):
|
def _build_xml_from_attrs(self):
|
||||||
"""
|
"""
|
||||||
|
@ -229,6 +229,8 @@ class Ui_MainWindow(object):
|
|||||||
self.ToolsOpenDataFolder = icon_action(mainWindow,
|
self.ToolsOpenDataFolder = icon_action(mainWindow,
|
||||||
u'ToolsOpenDataFolder', u':/general/general_open.png',
|
u'ToolsOpenDataFolder', u':/general/general_open.png',
|
||||||
category=UiStrings().Tools)
|
category=UiStrings().Tools)
|
||||||
|
self.updateThemeImages = base_action(mainWindow,
|
||||||
|
u'updateThemeImages', category=UiStrings().Tools)
|
||||||
action_list.add_category(UiStrings().Settings, CategoryOrder.standardMenu)
|
action_list.add_category(UiStrings().Settings, CategoryOrder.standardMenu)
|
||||||
self.settingsPluginListItem = shortcut_action(mainWindow,
|
self.settingsPluginListItem = shortcut_action(mainWindow,
|
||||||
u'settingsPluginListItem', [QtGui.QKeySequence(u'Alt+F7')],
|
u'settingsPluginListItem', [QtGui.QKeySequence(u'Alt+F7')],
|
||||||
@ -292,6 +294,7 @@ class Ui_MainWindow(object):
|
|||||||
self.SettingsConfigureItem))
|
self.SettingsConfigureItem))
|
||||||
add_actions(self.ToolsMenu, (self.ToolsAddToolItem, None))
|
add_actions(self.ToolsMenu, (self.ToolsAddToolItem, None))
|
||||||
add_actions(self.ToolsMenu, (self.ToolsOpenDataFolder, None))
|
add_actions(self.ToolsMenu, (self.ToolsOpenDataFolder, None))
|
||||||
|
add_actions(self.ToolsMenu, [self.updateThemeImages])
|
||||||
add_actions(self.HelpMenu, (self.HelpDocumentationItem,
|
add_actions(self.HelpMenu, (self.HelpDocumentationItem,
|
||||||
self.HelpOnlineHelpItem, None, self.helpWebSiteItem,
|
self.HelpOnlineHelpItem, None, self.helpWebSiteItem,
|
||||||
self.HelpAboutItem))
|
self.HelpAboutItem))
|
||||||
@ -433,6 +436,11 @@ class Ui_MainWindow(object):
|
|||||||
translate('OpenLP.MainWindow', 'Open &Data Folder...'))
|
translate('OpenLP.MainWindow', 'Open &Data Folder...'))
|
||||||
self.ToolsOpenDataFolder.setStatusTip(translate('OpenLP.MainWindow',
|
self.ToolsOpenDataFolder.setStatusTip(translate('OpenLP.MainWindow',
|
||||||
'Open the folder where songs, bibles and other data resides.'))
|
'Open the folder where songs, bibles and other data resides.'))
|
||||||
|
self.updateThemeImages.setText(
|
||||||
|
translate('OpenLP.MainWindow', 'Update Theme Images'))
|
||||||
|
self.updateThemeImages.setStatusTip(
|
||||||
|
translate('OpenLP.MainWindow', 'Update the preview images for all '
|
||||||
|
'themes.'))
|
||||||
self.ModeDefaultItem.setText(
|
self.ModeDefaultItem.setText(
|
||||||
translate('OpenLP.MainWindow', '&Default'))
|
translate('OpenLP.MainWindow', '&Default'))
|
||||||
self.ModeDefaultItem.setStatusTip(translate('OpenLP.MainWindow',
|
self.ModeDefaultItem.setStatusTip(translate('OpenLP.MainWindow',
|
||||||
@ -505,6 +513,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
QtCore.SIGNAL(u'triggered()'), self.onHelpOnLineHelpClicked)
|
QtCore.SIGNAL(u'triggered()'), self.onHelpOnLineHelpClicked)
|
||||||
QtCore.QObject.connect(self.ToolsOpenDataFolder,
|
QtCore.QObject.connect(self.ToolsOpenDataFolder,
|
||||||
QtCore.SIGNAL(u'triggered()'), self.onToolsOpenDataFolderClicked)
|
QtCore.SIGNAL(u'triggered()'), self.onToolsOpenDataFolderClicked)
|
||||||
|
QtCore.QObject.connect(self.updateThemeImages,
|
||||||
|
QtCore.SIGNAL(u'triggered()'), self.onUpdateThemeImages)
|
||||||
QtCore.QObject.connect(self.DisplayTagItem,
|
QtCore.QObject.connect(self.DisplayTagItem,
|
||||||
QtCore.SIGNAL(u'triggered()'), self.onDisplayTagItemClicked)
|
QtCore.SIGNAL(u'triggered()'), self.onDisplayTagItemClicked)
|
||||||
QtCore.QObject.connect(self.SettingsConfigureItem,
|
QtCore.QObject.connect(self.SettingsConfigureItem,
|
||||||
@ -615,11 +625,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
if self.liveController.display.isVisible():
|
if self.liveController.display.isVisible():
|
||||||
self.liveController.display.setFocus()
|
self.liveController.display.setFocus()
|
||||||
self.activateWindow()
|
self.activateWindow()
|
||||||
# On Windows, arguments contains the entire commandline
|
if len(self.arguments):
|
||||||
# So args[0]=='python' args[1]=='openlp.pyw'
|
|
||||||
# Therefore this approach is not going to work
|
|
||||||
# Bypass for now.
|
|
||||||
if len(self.arguments) and os.name != u'nt':
|
|
||||||
args = []
|
args = []
|
||||||
for a in self.arguments:
|
for a in self.arguments:
|
||||||
args.extend([a])
|
args.extend([a])
|
||||||
@ -717,6 +723,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
path = AppLocation.get_data_path()
|
path = AppLocation.get_data_path()
|
||||||
QtGui.QDesktopServices.openUrl(QtCore.QUrl("file:///" + path))
|
QtGui.QDesktopServices.openUrl(QtCore.QUrl("file:///" + path))
|
||||||
|
|
||||||
|
def onUpdateThemeImages(self):
|
||||||
|
"""
|
||||||
|
Updates the new theme preview images.
|
||||||
|
"""
|
||||||
|
self.themeManagerContents.updatePreviewImages()
|
||||||
|
|
||||||
def onDisplayTagItemClicked(self):
|
def onDisplayTagItemClicked(self):
|
||||||
"""
|
"""
|
||||||
Show the Settings dialog
|
Show the Settings dialog
|
||||||
@ -778,16 +790,18 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
def screenChanged(self):
|
def screenChanged(self):
|
||||||
"""
|
"""
|
||||||
The screen has changed to so tell the displays to update_display
|
The screen has changed so we have to update components such as the
|
||||||
their locations
|
renderer.
|
||||||
"""
|
"""
|
||||||
log.debug(u'screenChanged')
|
log.debug(u'screenChanged')
|
||||||
|
Receiver.send_message(u'cursor_busy')
|
||||||
self.image_manager.update_display()
|
self.image_manager.update_display()
|
||||||
self.renderer.update_display()
|
self.renderer.update_display()
|
||||||
self.liveController.screenSizeChanged()
|
|
||||||
self.previewController.screenSizeChanged()
|
self.previewController.screenSizeChanged()
|
||||||
|
self.liveController.screenSizeChanged()
|
||||||
self.setFocus()
|
self.setFocus()
|
||||||
self.activateWindow()
|
self.activateWindow()
|
||||||
|
Receiver.send_message(u'cursor_normal')
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
"""
|
"""
|
||||||
|
@ -757,7 +757,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
"""
|
"""
|
||||||
Called by a signal to select a specific item.
|
Called by a signal to select a specific item.
|
||||||
"""
|
"""
|
||||||
self.setItem(int(message[0]))
|
self.setItem(int(message))
|
||||||
|
|
||||||
def setItem(self, index):
|
def setItem(self, index):
|
||||||
"""
|
"""
|
||||||
|
@ -211,6 +211,11 @@ class SlideController(QtGui.QWidget):
|
|||||||
u'Go Live', u':/general/general_live.png',
|
u'Go Live', u':/general/general_live.png',
|
||||||
translate('OpenLP.SlideController', 'Move to live'),
|
translate('OpenLP.SlideController', 'Move to live'),
|
||||||
self.onGoLive)
|
self.onGoLive)
|
||||||
|
self.toolbar.addToolbarButton(
|
||||||
|
# Does not need translating - control string.
|
||||||
|
u'Add to Service', u':/general/general_add.png',
|
||||||
|
translate('OpenLP.SlideController', 'Add to Service'),
|
||||||
|
self.onPreviewAddToService)
|
||||||
self.toolbar.addToolbarSeparator(u'Close Separator')
|
self.toolbar.addToolbarSeparator(u'Close Separator')
|
||||||
self.toolbar.addToolbarButton(
|
self.toolbar.addToolbarButton(
|
||||||
# Does not need translating - control string.
|
# Does not need translating - control string.
|
||||||
@ -1044,12 +1049,26 @@ class SlideController(QtGui.QWidget):
|
|||||||
Receiver.send_message(u'%s_edit' % self.serviceItem.name.lower(),
|
Receiver.send_message(u'%s_edit' % self.serviceItem.name.lower(),
|
||||||
u'P:%s' % self.serviceItem.edit_id)
|
u'P:%s' % self.serviceItem.edit_id)
|
||||||
|
|
||||||
|
def onPreviewAddToService(self):
|
||||||
|
"""
|
||||||
|
From the preview display request the Item to be added to service
|
||||||
|
"""
|
||||||
|
self.parent.ServiceManagerContents.addServiceItem(self.serviceItem)
|
||||||
|
|
||||||
def onGoLiveClick(self):
|
def onGoLiveClick(self):
|
||||||
"""
|
"""
|
||||||
triggered by clicking the Preview slide items
|
triggered by clicking the Preview slide items
|
||||||
"""
|
"""
|
||||||
if QtCore.QSettings().value(u'advanced/double click live',
|
if QtCore.QSettings().value(u'advanced/double click live',
|
||||||
QtCore.QVariant(False)).toBool():
|
QtCore.QVariant(False)).toBool():
|
||||||
|
# Live and Preview have issues if we have video or presentations
|
||||||
|
# playing in both at the same time.
|
||||||
|
if self.serviceItem.is_command():
|
||||||
|
Receiver.send_message(u'%s_stop' %
|
||||||
|
self.serviceItem.name.lower(),
|
||||||
|
[self.serviceItem, self.isLive])
|
||||||
|
if self.serviceItem.is_media():
|
||||||
|
self.onMediaClose()
|
||||||
self.onGoLive()
|
self.onGoLive()
|
||||||
|
|
||||||
def onGoLive(self):
|
def onGoLive(self):
|
||||||
|
@ -660,6 +660,18 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
pixmap.save(thumb, u'png')
|
pixmap.save(thumb, u'png')
|
||||||
log.debug(u'Theme image written to %s', samplepathname)
|
log.debug(u'Theme image written to %s', samplepathname)
|
||||||
|
|
||||||
|
def updatePreviewImages(self):
|
||||||
|
"""
|
||||||
|
Called to update the themes' preview images.
|
||||||
|
"""
|
||||||
|
self.mainwindow.displayProgressBar(len(self.themelist))
|
||||||
|
for theme in self.themelist:
|
||||||
|
self.mainwindow.incrementProgressBar()
|
||||||
|
self.generateAndSaveImage(
|
||||||
|
self.path, theme, self.getThemeData(theme))
|
||||||
|
self.mainwindow.finishedProgressBar()
|
||||||
|
self.loadThemes()
|
||||||
|
|
||||||
def generateImage(self, themeData, forcePage=False):
|
def generateImage(self, themeData, forcePage=False):
|
||||||
"""
|
"""
|
||||||
Call the renderer to build a Sample Image
|
Call the renderer to build a Sample Image
|
||||||
|
@ -342,7 +342,7 @@ def add_actions(target, actions):
|
|||||||
The menu or toolbar to add actions to.
|
The menu or toolbar to add actions to.
|
||||||
|
|
||||||
``actions``
|
``actions``
|
||||||
The actions to be added. An action consisting of the keyword 'None'
|
The actions to be added. An action consisting of the keyword ``None``
|
||||||
will result in a separator being inserted into the target.
|
will result in a separator being inserted into the target.
|
||||||
"""
|
"""
|
||||||
for action in actions:
|
for action in actions:
|
||||||
|
@ -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)
|
||||||
critical_error_message_box(
|
if show_error:
|
||||||
translate('BiblesPlugin', 'No Book Found'),
|
critical_error_message_box(
|
||||||
translate('BiblesPlugin', 'No matching book '
|
translate('BiblesPlugin', 'No Book Found'),
|
||||||
'could be found in this Bible. Check that you have '
|
translate('BiblesPlugin', 'No matching book '
|
||||||
'spelled the name of the book correctly.'))
|
'could be found in this Bible. Check that you '
|
||||||
|
'have spelled the name of the book correctly.'))
|
||||||
return verse_list
|
return verse_list
|
||||||
|
|
||||||
def verse_search(self, text):
|
def verse_search(self, text):
|
||||||
|
@ -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,11 +453,12 @@ 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:
|
||||||
critical_error_message_box(
|
if show_error:
|
||||||
translate('BiblesPlugin', 'No Book Found'),
|
critical_error_message_box(
|
||||||
translate('BiblesPlugin', 'No matching '
|
translate('BiblesPlugin', 'No Book Found'),
|
||||||
'book could be found in this Bible. Check that you '
|
translate('BiblesPlugin', 'No matching '
|
||||||
'have spelled the name of the book correctly.'))
|
'book could be found in this Bible. Check that you '
|
||||||
|
'have spelled the name of the book correctly.'))
|
||||||
return []
|
return []
|
||||||
db_book = self.create_book(book_details[u'name'],
|
db_book = self.create_book(book_details[u'name'],
|
||||||
book_details[u'abbreviation'],
|
book_details[u'abbreviation'],
|
||||||
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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,32 +252,34 @@ 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:
|
||||||
Receiver.send_message(u'openlp_information_message', {
|
if show_error:
|
||||||
u'title': translate('BiblesPlugin.BibleManager',
|
Receiver.send_message(u'openlp_information_message', {
|
||||||
'No Bibles Available'),
|
u'title': translate('BiblesPlugin.BibleManager',
|
||||||
u'message': translate('BiblesPlugin.BibleManager',
|
'No Bibles Available'),
|
||||||
'There are no Bibles currently installed. Please use the '
|
u'message': translate('BiblesPlugin.BibleManager',
|
||||||
'Import Wizard to install one or more Bibles.')
|
'There are no Bibles currently installed. Please use the '
|
||||||
})
|
'Import Wizard to install one or more Bibles.')
|
||||||
|
})
|
||||||
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:
|
||||||
Receiver.send_message(u'openlp_information_message', {
|
if show_error:
|
||||||
u'title': translate('BiblesPlugin.BibleManager',
|
Receiver.send_message(u'openlp_information_message', {
|
||||||
'Scripture Reference Error'),
|
u'title': translate('BiblesPlugin.BibleManager',
|
||||||
u'message': translate('BiblesPlugin.BibleManager',
|
'Scripture Reference Error'),
|
||||||
'Your scripture reference is either not supported by OpenLP '
|
u'message': translate('BiblesPlugin.BibleManager',
|
||||||
'or is invalid. Please make sure your reference conforms to '
|
'Your scripture reference is either not supported by '
|
||||||
'one of the following patterns:\n\n'
|
'OpenLP or is invalid. Please make sure your reference '
|
||||||
'Book Chapter\n'
|
'conforms to one of the following patterns:\n\n'
|
||||||
'Book Chapter-Chapter\n'
|
'Book Chapter\n'
|
||||||
'Book Chapter:Verse-Verse\n'
|
'Book Chapter-Chapter\n'
|
||||||
'Book Chapter:Verse-Verse,Verse-Verse\n'
|
'Book Chapter:Verse-Verse\n'
|
||||||
'Book Chapter:Verse-Verse,Chapter:Verse-Verse\n'
|
'Book Chapter:Verse-Verse,Verse-Verse\n'
|
||||||
'Book Chapter:Verse-Chapter:Verse')
|
'Book Chapter:Verse-Verse,Chapter:Verse-Verse\n'
|
||||||
})
|
'Book Chapter:Verse-Chapter:Verse')
|
||||||
|
})
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def verse_search(self, bible, second_bible, text):
|
def verse_search(self, bible, second_bible, text):
|
||||||
|
@ -61,6 +61,7 @@ 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 = {}
|
||||||
self.check_search_result()
|
self.check_search_result()
|
||||||
@ -646,6 +647,19 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
Receiver.send_message(u'openlp_process_events')
|
Receiver.send_message(u'openlp_process_events')
|
||||||
|
|
||||||
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.
|
||||||
@ -665,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),
|
||||||
@ -697,10 +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 generateSlideData(self, service_item, item=None, xmlVersion=False):
|
def generateSlideData(self, service_item, item=None, xmlVersion=False):
|
||||||
"""
|
"""
|
||||||
@ -708,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''
|
||||||
@ -717,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'))
|
||||||
@ -752,11 +767,11 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
else:
|
else:
|
||||||
bible_text = u'%s %s %s\n' % (bible_text, verse_text, text)
|
bible_text = u'%s %s %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())
|
||||||
@ -764,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())
|
||||||
@ -787,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.
|
||||||
|
|
||||||
@ -801,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')
|
||||||
@ -825,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.
|
||||||
|
|
||||||
@ -838,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'))
|
||||||
@ -896,3 +907,22 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
if self.settings.display_style == DisplayStyle.Square:
|
if self.settings.display_style == DisplayStyle.Square:
|
||||||
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 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
|
||||||
|
@ -65,6 +65,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
|||||||
QtCore.SIGNAL(u'theme_update_list'), self.loadThemes)
|
QtCore.SIGNAL(u'theme_update_list'), self.loadThemes)
|
||||||
QtCore.QObject.connect(self.slideListView,
|
QtCore.QObject.connect(self.slideListView,
|
||||||
QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
|
QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
|
||||||
|
QtCore.QObject.connect(self.slideListView,
|
||||||
|
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
|
||||||
|
self.onEditButtonPressed)
|
||||||
|
|
||||||
def loadThemes(self, themelist):
|
def loadThemes(self, themelist):
|
||||||
self.themeComboBox.clear()
|
self.themeComboBox.clear()
|
||||||
@ -111,6 +114,8 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
|||||||
def accept(self):
|
def accept(self):
|
||||||
log.debug(u'accept')
|
log.debug(u'accept')
|
||||||
if self.saveCustom():
|
if self.saveCustom():
|
||||||
|
Receiver.send_message(u'custom_set_autoselect_item',
|
||||||
|
self.customSlide.title)
|
||||||
Receiver.send_message(u'custom_load_list')
|
Receiver.send_message(u'custom_load_list')
|
||||||
QtGui.QDialog.accept(self)
|
QtGui.QDialog.accept(self)
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import translate, SpellTextEdit
|
from openlp.core.lib import translate, SpellTextEdit, build_icon
|
||||||
from openlp.core.lib.ui import create_accept_reject_button_box
|
from openlp.core.lib.ui import create_accept_reject_button_box
|
||||||
|
|
||||||
class Ui_CustomSlideEditDialog(object):
|
class Ui_CustomSlideEditDialog(object):
|
||||||
@ -39,9 +39,15 @@ class Ui_CustomSlideEditDialog(object):
|
|||||||
self.dialogLayout.addWidget(self.slideTextEdit)
|
self.dialogLayout.addWidget(self.slideTextEdit)
|
||||||
self.buttonBox = create_accept_reject_button_box(customSlideEditDialog)
|
self.buttonBox = create_accept_reject_button_box(customSlideEditDialog)
|
||||||
self.splitButton = QtGui.QPushButton(customSlideEditDialog)
|
self.splitButton = QtGui.QPushButton(customSlideEditDialog)
|
||||||
|
self.splitButton.setIcon(build_icon(u':/general/general_add.png'))
|
||||||
self.splitButton.setObjectName(u'splitButton')
|
self.splitButton.setObjectName(u'splitButton')
|
||||||
self.buttonBox.addButton(self.splitButton,
|
self.buttonBox.addButton(self.splitButton,
|
||||||
QtGui.QDialogButtonBox.ActionRole)
|
QtGui.QDialogButtonBox.ActionRole)
|
||||||
|
self.insertButton = QtGui.QPushButton(customSlideEditDialog)
|
||||||
|
self.insertButton.setIcon(build_icon(u':/general/general_add.png'))
|
||||||
|
self.insertButton.setObjectName(u'insertButton')
|
||||||
|
self.buttonBox.addButton(self.insertButton,
|
||||||
|
QtGui.QDialogButtonBox.ActionRole)
|
||||||
self.dialogLayout.addWidget(self.buttonBox)
|
self.dialogLayout.addWidget(self.buttonBox)
|
||||||
self.retranslateUi(customSlideEditDialog)
|
self.retranslateUi(customSlideEditDialog)
|
||||||
QtCore.QMetaObject.connectSlotsByName(customSlideEditDialog)
|
QtCore.QMetaObject.connectSlotsByName(customSlideEditDialog)
|
||||||
@ -50,5 +56,10 @@ class Ui_CustomSlideEditDialog(object):
|
|||||||
self.splitButton.setText(
|
self.splitButton.setText(
|
||||||
translate('CustomPlugin.EditCustomForm', 'Split Slide'))
|
translate('CustomPlugin.EditCustomForm', 'Split Slide'))
|
||||||
self.splitButton.setToolTip(
|
self.splitButton.setToolTip(
|
||||||
|
translate('CustomPlugin.EditCustomForm', 'Split a slide into two '
|
||||||
|
'only if it does not fit on the screen as one slide.'))
|
||||||
|
self.insertButton.setText(
|
||||||
|
translate('CustomPlugin.EditCustomForm', 'Insert Slide'))
|
||||||
|
self.insertButton.setToolTip(
|
||||||
translate('CustomPlugin.EditCustomForm', 'Split a slide into two '
|
translate('CustomPlugin.EditCustomForm', 'Split a slide into two '
|
||||||
'by inserting a slide splitter.'))
|
'by inserting a slide splitter.'))
|
||||||
|
@ -44,6 +44,8 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog):
|
|||||||
QtGui.QDialog.__init__(self, parent)
|
QtGui.QDialog.__init__(self, parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
# Connecting signals and slots
|
# Connecting signals and slots
|
||||||
|
QtCore.QObject.connect(self.insertButton,
|
||||||
|
QtCore.SIGNAL(u'clicked()'), self.onInsertButtonPressed)
|
||||||
QtCore.QObject.connect(self.splitButton,
|
QtCore.QObject.connect(self.splitButton,
|
||||||
QtCore.SIGNAL(u'clicked()'), self.onSplitButtonPressed)
|
QtCore.SIGNAL(u'clicked()'), self.onSplitButtonPressed)
|
||||||
|
|
||||||
@ -65,7 +67,7 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog):
|
|||||||
"""
|
"""
|
||||||
return self.slideTextEdit.toPlainText().split(u'\n[===]\n')
|
return self.slideTextEdit.toPlainText().split(u'\n[===]\n')
|
||||||
|
|
||||||
def onSplitButtonPressed(self):
|
def onInsertButtonPressed(self):
|
||||||
"""
|
"""
|
||||||
Adds a slide split at the cursor.
|
Adds a slide split at the cursor.
|
||||||
"""
|
"""
|
||||||
@ -73,3 +75,12 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog):
|
|||||||
self.slideTextEdit.insertPlainText(u'\n')
|
self.slideTextEdit.insertPlainText(u'\n')
|
||||||
self.slideTextEdit.insertPlainText(u'[===]\n')
|
self.slideTextEdit.insertPlainText(u'[===]\n')
|
||||||
self.slideTextEdit.setFocus()
|
self.slideTextEdit.setFocus()
|
||||||
|
|
||||||
|
def onSplitButtonPressed(self):
|
||||||
|
"""
|
||||||
|
Adds a virtual split at cursor.
|
||||||
|
"""
|
||||||
|
if self.slideTextEdit.textCursor().columnNumber() != 0:
|
||||||
|
self.slideTextEdit.insertPlainText(u'\n')
|
||||||
|
self.slideTextEdit.insertPlainText(u'[---]')
|
||||||
|
self.slideTextEdit.setFocus()
|
||||||
|
@ -27,15 +27,25 @@
|
|||||||
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, translate
|
||||||
|
from openlp.core.lib.searchedit import SearchEdit
|
||||||
from openlp.core.lib.ui import UiStrings
|
from openlp.core.lib.ui import UiStrings
|
||||||
from openlp.plugins.custom.lib import CustomXMLParser
|
from openlp.plugins.custom.lib import CustomXMLParser
|
||||||
from openlp.plugins.custom.lib.db import CustomSlide
|
from openlp.plugins.custom.lib.db import CustomSlide
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class CustomSearch(object):
|
||||||
|
"""
|
||||||
|
An enumeration for custom search methods.
|
||||||
|
"""
|
||||||
|
Titles = 1
|
||||||
|
Themes = 2
|
||||||
|
|
||||||
|
|
||||||
class CustomMediaItem(MediaManagerItem):
|
class CustomMediaItem(MediaManagerItem):
|
||||||
"""
|
"""
|
||||||
This is the custom media manager item for Custom Slides.
|
This is the custom media manager item for Custom Slides.
|
||||||
@ -47,12 +57,48 @@ 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
|
||||||
self.manager = parent.manager
|
self.manager = parent.manager
|
||||||
|
|
||||||
def addEndHeaderBar(self):
|
def addEndHeaderBar(self):
|
||||||
|
self.addToolbarSeparator()
|
||||||
|
self.searchWidget = QtGui.QWidget(self)
|
||||||
|
self.searchWidget.setObjectName(u'searchWidget')
|
||||||
|
self.searchLayout = QtGui.QVBoxLayout(self.searchWidget)
|
||||||
|
self.searchLayout.setObjectName(u'searchLayout')
|
||||||
|
self.searchTextLayout = QtGui.QFormLayout()
|
||||||
|
self.searchTextLayout.setObjectName(u'searchTextLayout')
|
||||||
|
self.searchTextLabel = QtGui.QLabel(self.searchWidget)
|
||||||
|
self.searchTextLabel.setObjectName(u'searchTextLabel')
|
||||||
|
self.searchTextEdit = SearchEdit(self.searchWidget)
|
||||||
|
self.searchTextEdit.setObjectName(u'searchTextEdit')
|
||||||
|
self.searchTextLabel.setBuddy(self.searchTextEdit)
|
||||||
|
self.searchTextLayout.addRow(self.searchTextLabel, self.searchTextEdit)
|
||||||
|
self.searchLayout.addLayout(self.searchTextLayout)
|
||||||
|
self.searchButtonLayout = QtGui.QHBoxLayout()
|
||||||
|
self.searchButtonLayout.setObjectName(u'searchButtonLayout')
|
||||||
|
self.searchButtonLayout.addStretch()
|
||||||
|
self.searchTextButton = QtGui.QPushButton(self.searchWidget)
|
||||||
|
self.searchTextButton.setObjectName(u'searchTextButton')
|
||||||
|
self.searchButtonLayout.addWidget(self.searchTextButton)
|
||||||
|
self.searchLayout.addLayout(self.searchButtonLayout)
|
||||||
|
self.pageLayout.addWidget(self.searchWidget)
|
||||||
|
# Signals and slots
|
||||||
|
QtCore.QObject.connect(self.searchTextEdit,
|
||||||
|
QtCore.SIGNAL(u'returnPressed()'), self.onSearchTextButtonClick)
|
||||||
|
QtCore.QObject.connect(self.searchTextButton,
|
||||||
|
QtCore.SIGNAL(u'pressed()'), self.onSearchTextButtonClick)
|
||||||
|
QtCore.QObject.connect(self.searchTextEdit,
|
||||||
|
QtCore.SIGNAL(u'textChanged(const QString&)'),
|
||||||
|
self.onSearchTextEditChanged)
|
||||||
|
QtCore.QObject.connect(self.searchTextEdit,
|
||||||
|
QtCore.SIGNAL(u'cleared()'), self.onClearTextButtonClick)
|
||||||
|
QtCore.QObject.connect(self.searchTextEdit,
|
||||||
|
QtCore.SIGNAL(u'searchTypeChanged(int)'),
|
||||||
|
self.onSearchTextButtonClick)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'custom_edit'), self.onRemoteEdit)
|
QtCore.SIGNAL(u'custom_edit'), self.onRemoteEdit)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
@ -62,9 +108,22 @@ class CustomMediaItem(MediaManagerItem):
|
|||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'custom_preview'), self.onPreviewClick)
|
QtCore.SIGNAL(u'custom_preview'), self.onPreviewClick)
|
||||||
|
|
||||||
|
def retranslateUi(self):
|
||||||
|
self.searchTextLabel.setText(u'%s:' % UiStrings().Search)
|
||||||
|
self.searchTextButton.setText(UiStrings().Search)
|
||||||
|
|
||||||
def initialise(self):
|
def initialise(self):
|
||||||
|
self.searchTextEdit.setSearchTypes([
|
||||||
|
(CustomSearch.Titles, u':/songs/song_search_title.png',
|
||||||
|
translate('SongsPlugin.MediaItem', 'Titles')),
|
||||||
|
(CustomSearch.Themes, u':/slides/slide_theme.png',
|
||||||
|
UiStrings().Themes)
|
||||||
|
])
|
||||||
self.loadList(self.manager.get_all_objects(
|
self.loadList(self.manager.get_all_objects(
|
||||||
CustomSlide, order_by_ref=CustomSlide.title))
|
CustomSlide, order_by_ref=CustomSlide.title))
|
||||||
|
self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value(
|
||||||
|
u'%s/last search type' % self.settingsSection,
|
||||||
|
QtCore.QVariant(CustomSearch.Titles)).toInt()[0])
|
||||||
# Called to redisplay the custom list screen edith from a search
|
# Called to redisplay the custom list screen edith from a search
|
||||||
# or from the exit of the Custom edit dialog. If remote editing is
|
# or from the exit of the Custom edit dialog. If remote editing is
|
||||||
# active trigger it and clean up so it will not update again.
|
# active trigger it and clean up so it will not update again.
|
||||||
@ -81,6 +140,9 @@ class CustomMediaItem(MediaManagerItem):
|
|||||||
custom_name.setData(
|
custom_name.setData(
|
||||||
QtCore.Qt.UserRole, QtCore.QVariant(customSlide.id))
|
QtCore.Qt.UserRole, QtCore.QVariant(customSlide.id))
|
||||||
self.listView.addItem(custom_name)
|
self.listView.addItem(custom_name)
|
||||||
|
# Auto-select the item if name has been set
|
||||||
|
if customSlide.title == self.autoSelectItem :
|
||||||
|
self.listView.setCurrentItem(custom_name)
|
||||||
|
|
||||||
def onNewClick(self):
|
def onNewClick(self):
|
||||||
self.parent.edit_custom_form.loadCustom(0)
|
self.parent.edit_custom_form.loadCustom(0)
|
||||||
@ -161,4 +223,59 @@ class CustomMediaItem(MediaManagerItem):
|
|||||||
else:
|
else:
|
||||||
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 onSearchTextButtonClick(self):
|
||||||
|
# Save the current search type to the configuration.
|
||||||
|
QtCore.QSettings().setValue(u'%s/last search type' %
|
||||||
|
self.settingsSection,
|
||||||
|
QtCore.QVariant(self.searchTextEdit.currentSearchType()))
|
||||||
|
# Reload the list considering the new search type.
|
||||||
|
search_keywords = unicode(self.searchTextEdit.displayText())
|
||||||
|
search_results = []
|
||||||
|
search_type = self.searchTextEdit.currentSearchType()
|
||||||
|
if search_type == CustomSearch.Titles:
|
||||||
|
log.debug(u'Titles Search')
|
||||||
|
search_results = self.parent.manager.get_all_objects(CustomSlide,
|
||||||
|
CustomSlide.title.like(u'%' + self.whitespace.sub(u' ',
|
||||||
|
search_keywords) + u'%'), order_by_ref=CustomSlide.title)
|
||||||
|
self.loadList(search_results)
|
||||||
|
elif search_type == CustomSearch.Themes:
|
||||||
|
log.debug(u'Theme Search')
|
||||||
|
search_results = self.parent.manager.get_all_objects(CustomSlide,
|
||||||
|
CustomSlide.theme_name.like(u'%' + self.whitespace.sub(u' ',
|
||||||
|
search_keywords) + u'%'), order_by_ref=CustomSlide.title)
|
||||||
|
self.loadList(search_results)
|
||||||
|
self.check_search_result()
|
||||||
|
|
||||||
|
def onSearchTextEditChanged(self, text):
|
||||||
|
"""
|
||||||
|
If search as type enabled invoke the search on each key press.
|
||||||
|
If the Title is being searched do not start till 2 characters
|
||||||
|
have been entered.
|
||||||
|
"""
|
||||||
|
search_length = 2
|
||||||
|
if len(text) > search_length:
|
||||||
|
self.onSearchTextButtonClick()
|
||||||
|
elif len(text) == 0:
|
||||||
|
self.onClearTextButtonClick()
|
||||||
|
|
||||||
|
def onClearTextButtonClick(self):
|
||||||
|
"""
|
||||||
|
Clear the search text.
|
||||||
|
"""
|
||||||
|
self.searchTextEdit.clear()
|
||||||
|
self.onSearchTextButtonClick()
|
||||||
|
|
||||||
|
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'
|
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,51 +131,51 @@ 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]
|
||||||
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
|
|
||||||
else:
|
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
|
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):
|
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
|
||||||
|
@ -49,6 +49,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'),
|
||||||
@ -186,3 +187,14 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
item_name.setIcon(build_icon(img))
|
item_name.setIcon(build_icon(img))
|
||||||
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
|
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
|
||||||
self.listView.addItem(item_name)
|
self.listView.addItem(item_name)
|
||||||
|
|
||||||
|
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
|
||||||
|
@ -45,6 +45,7 @@ else:
|
|||||||
try:
|
try:
|
||||||
import uno
|
import uno
|
||||||
from com.sun.star.beans import PropertyValue
|
from com.sun.star.beans import PropertyValue
|
||||||
|
from com.sun.star.task import ErrorCodeIOException
|
||||||
uno_available = True
|
uno_available = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
uno_available = False
|
uno_available = False
|
||||||
@ -286,6 +287,9 @@ class ImpressDocument(PresentationDocument):
|
|||||||
doc.storeToURL(urlpath, props)
|
doc.storeToURL(urlpath, props)
|
||||||
self.convert_thumbnail(path, idx + 1)
|
self.convert_thumbnail(path, idx + 1)
|
||||||
delete_file(path)
|
delete_file(path)
|
||||||
|
except ErrorCodeIOException, exception:
|
||||||
|
log.exception(u'ERROR! ErrorCodeIOException %d' %
|
||||||
|
exception.ErrCode)
|
||||||
except:
|
except:
|
||||||
log.exception(u'%s - Unable to store openoffice preview' % path)
|
log.exception(u'%s - Unable to store openoffice preview' % path)
|
||||||
|
|
||||||
|
@ -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,17 +232,19 @@ 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:
|
||||||
if len(items) > 1:
|
items = [item]
|
||||||
return False
|
else:
|
||||||
|
items = self.listView.selectedItems()
|
||||||
|
if len(items) > 1:
|
||||||
|
return False
|
||||||
service_item.title = unicode(self.displayTypeComboBox.currentText())
|
service_item.title = unicode(self.displayTypeComboBox.currentText())
|
||||||
service_item.shortname = unicode(self.displayTypeComboBox.currentText())
|
service_item.shortname = unicode(self.displayTypeComboBox.currentText())
|
||||||
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
|
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
|
||||||
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
|
||||||
|
@ -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>
|
||||||
|
@ -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,6 +204,55 @@ 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 item = $("<li>").text(value[1]);
|
||||||
|
var golive = $("<a href=\"#\">Go Live</a>").attr("value", value[0]).click(OpenLP.goLive);
|
||||||
|
var additem = $("<a href=\"#\">Add To Service</a>").attr("value", value[0]).click(OpenLP.addToService);
|
||||||
|
item.append($("<ul>").append($("<li>").append(golive)).append($("<li>").append(additem)));
|
||||||
|
ul.append(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ul.listview("refresh");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
goLive: function (event) {
|
||||||
|
var item = OpenLP.getElement(event);
|
||||||
|
var id = item.attr("value");
|
||||||
|
var text = JSON.stringify({"request": {"id": id}});
|
||||||
|
$.getJSON(
|
||||||
|
"/api/" + $("#search-plugin").val() + "/live",
|
||||||
|
{"data": text})
|
||||||
|
$.mobile.changePage("slide-controller");
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
addToService: function (event) {
|
||||||
|
var item = OpenLP.getElement(event);
|
||||||
|
var id = item.attr("value");
|
||||||
|
var text = JSON.stringify({"request": {"id": id}});
|
||||||
|
$.getJSON(
|
||||||
|
"/api/" + $("#search-plugin").val() + "/add",
|
||||||
|
{"data": text},
|
||||||
|
function () {
|
||||||
|
history.back();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Service Manager
|
// Service Manager
|
||||||
@ -207,7 +271,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();
|
||||||
|
@ -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,11 @@ 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),
|
||||||
|
(r'^/api/(.*)/add$', self.add_to_service)
|
||||||
]
|
]
|
||||||
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 +413,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 +447,60 @@ 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 add_to_service(self, type):
|
||||||
|
"""
|
||||||
|
Add item of type ``type`` to the end of the service
|
||||||
|
"""
|
||||||
|
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:
|
||||||
|
item_id = plugin.mediaItem.createItemFromId(id)
|
||||||
|
plugin.mediaItem.addToService(item_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():
|
||||||
|
@ -695,6 +695,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
self.clearCaches()
|
self.clearCaches()
|
||||||
if self._validate_song():
|
if self._validate_song():
|
||||||
self.saveSong()
|
self.saveSong()
|
||||||
|
Receiver.send_message(u'songs_set_autoselect_item',
|
||||||
|
unicode(self.titleEdit.text()))
|
||||||
Receiver.send_message(u'songs_load_list')
|
Receiver.send_message(u'songs_load_list')
|
||||||
QtGui.QDialog.accept(self)
|
QtGui.QDialog.accept(self)
|
||||||
|
|
||||||
|
@ -42,6 +42,10 @@ class Ui_EditVerseDialog(object):
|
|||||||
self.dialogLayout.addWidget(self.verseTextEdit)
|
self.dialogLayout.addWidget(self.verseTextEdit)
|
||||||
self.verseTypeLayout = QtGui.QHBoxLayout()
|
self.verseTypeLayout = QtGui.QHBoxLayout()
|
||||||
self.verseTypeLayout.setObjectName(u'verseTypeLayout')
|
self.verseTypeLayout.setObjectName(u'verseTypeLayout')
|
||||||
|
self.splitButton = QtGui.QPushButton(editVerseDialog)
|
||||||
|
self.splitButton.setIcon(build_icon(u':/general/general_add.png'))
|
||||||
|
self.splitButton.setObjectName(u'splitButton')
|
||||||
|
self.verseTypeLayout.addWidget(self.splitButton)
|
||||||
self.verseTypeLabel = QtGui.QLabel(editVerseDialog)
|
self.verseTypeLabel = QtGui.QLabel(editVerseDialog)
|
||||||
self.verseTypeLabel.setObjectName(u'verseTypeLabel')
|
self.verseTypeLabel.setObjectName(u'verseTypeLabel')
|
||||||
self.verseTypeLayout.addWidget(self.verseTypeLabel)
|
self.verseTypeLayout.addWidget(self.verseTypeLabel)
|
||||||
@ -84,5 +88,13 @@ class Ui_EditVerseDialog(object):
|
|||||||
VerseType.TranslatedNames[VerseType.Ending])
|
VerseType.TranslatedNames[VerseType.Ending])
|
||||||
self.verseTypeComboBox.setItemText(VerseType.Other,
|
self.verseTypeComboBox.setItemText(VerseType.Other,
|
||||||
VerseType.TranslatedNames[VerseType.Other])
|
VerseType.TranslatedNames[VerseType.Other])
|
||||||
|
self.splitButton.setText(
|
||||||
|
translate('SongsPlugin.EditVerseForm', '&Split'))
|
||||||
|
self.splitButton.setToolTip(
|
||||||
|
translate('SongsPlugin.EditVerseForm', 'Split a slide into two '
|
||||||
|
'only if it does not fit on the screen as one slide.'))
|
||||||
self.insertButton.setText(
|
self.insertButton.setText(
|
||||||
translate('SongsPlugin.EditVerseForm', '&Insert'))
|
translate('SongsPlugin.EditVerseForm', '&Insert'))
|
||||||
|
self.insertButton.setToolTip(
|
||||||
|
translate('SongsPlugin.EditVerseForm', 'Split a slide into two '
|
||||||
|
'by inserting a verse splitter.'))
|
||||||
|
@ -51,6 +51,8 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
|||||||
self.contextMenu)
|
self.contextMenu)
|
||||||
QtCore.QObject.connect(self.insertButton, QtCore.SIGNAL(u'clicked()'),
|
QtCore.QObject.connect(self.insertButton, QtCore.SIGNAL(u'clicked()'),
|
||||||
self.onInsertButtonClicked)
|
self.onInsertButtonClicked)
|
||||||
|
QtCore.QObject.connect(self.splitButton, QtCore.SIGNAL(u'clicked()'),
|
||||||
|
self.onSplitButtonClicked)
|
||||||
QtCore.QObject.connect(self.verseTextEdit,
|
QtCore.QObject.connect(self.verseTextEdit,
|
||||||
QtCore.SIGNAL(u'cursorPositionChanged()'),
|
QtCore.SIGNAL(u'cursorPositionChanged()'),
|
||||||
self.onCursorPositionChanged)
|
self.onCursorPositionChanged)
|
||||||
@ -70,6 +72,13 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
|||||||
(verse_tag, verse_num))
|
(verse_tag, verse_num))
|
||||||
self.verseTextEdit.setFocus()
|
self.verseTextEdit.setFocus()
|
||||||
|
|
||||||
|
def onSplitButtonClicked(self):
|
||||||
|
verse_type_index = self.verseTypeComboBox.currentIndex()
|
||||||
|
if self.verseTextEdit.textCursor().columnNumber() != 0:
|
||||||
|
self.verseTextEdit.insertPlainText(u'\n')
|
||||||
|
self.verseTextEdit.insertPlainText(u'[---]')
|
||||||
|
self.verseTextEdit.setFocus()
|
||||||
|
|
||||||
def onInsertButtonClicked(self):
|
def onInsertButtonClicked(self):
|
||||||
verse_type_index = self.verseTypeComboBox.currentIndex()
|
verse_type_index = self.verseTypeComboBox.currentIndex()
|
||||||
self.insertVerse(VerseType.Tags[verse_type_index],
|
self.insertVerse(VerseType.Tags[verse_type_index],
|
||||||
|
@ -422,7 +422,8 @@ class FoilPresenter(object):
|
|||||||
VerseType.Tags[VerseType.PreChorus]: 1
|
VerseType.Tags[VerseType.PreChorus]: 1
|
||||||
}
|
}
|
||||||
for strophe in foilpresenterfolie.strophen.strophe:
|
for strophe in foilpresenterfolie.strophen.strophe:
|
||||||
text = self._child(strophe.text_)
|
text = self._child(strophe.text_) if hasattr(strophe, u'text_') \
|
||||||
|
else u''
|
||||||
verse_name = self._child(strophe.key)
|
verse_name = self._child(strophe.key)
|
||||||
children = strophe.getchildren()
|
children = strophe.getchildren()
|
||||||
sortnr = False
|
sortnr = False
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import locale
|
import locale
|
||||||
import re
|
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from sqlalchemy.sql import or_
|
from sqlalchemy.sql import or_
|
||||||
@ -72,8 +71,8 @@ class SongMediaItem(MediaManagerItem):
|
|||||||
# which Song is required.
|
# which Song is required.
|
||||||
self.remoteSong = -1
|
self.remoteSong = -1
|
||||||
self.editItem = None
|
self.editItem = None
|
||||||
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 +170,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')
|
||||||
@ -197,10 +192,18 @@ class SongMediaItem(MediaManagerItem):
|
|||||||
elif search_type == SongSearch.Themes:
|
elif search_type == SongSearch.Themes:
|
||||||
log.debug(u'Theme Search')
|
log.debug(u'Theme Search')
|
||||||
search_results = self.parent.manager.get_all_objects(Song,
|
search_results = self.parent.manager.get_all_objects(Song,
|
||||||
Song.theme_name == search_keywords)
|
Song.theme_name.like(u'%' + self.whitespace.sub(u' ',
|
||||||
|
search_keywords) + u'%'))
|
||||||
self.displayResultsSong(search_results)
|
self.displayResultsSong(search_results)
|
||||||
self.check_search_result()
|
self.check_search_result()
|
||||||
|
|
||||||
|
def searchEntire(self, search_keywords):
|
||||||
|
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):
|
||||||
"""
|
"""
|
||||||
Handle the exit from the edit dialog and trigger remote updates
|
Handle the exit from the edit dialog and trigger remote updates
|
||||||
@ -234,6 +237,9 @@ class SongMediaItem(MediaManagerItem):
|
|||||||
song_name = QtGui.QListWidgetItem(song_detail)
|
song_name = QtGui.QListWidgetItem(song_detail)
|
||||||
song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id))
|
song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id))
|
||||||
self.listView.addItem(song_name)
|
self.listView.addItem(song_name)
|
||||||
|
# Auto-select the item if name has been set
|
||||||
|
if song.title == self.autoSelectItem :
|
||||||
|
self.listView.setCurrentItem(song_name)
|
||||||
|
|
||||||
def displayResultsAuthor(self, searchresults):
|
def displayResultsAuthor(self, searchresults):
|
||||||
log.debug(u'display results Author')
|
log.debug(u'display results Author')
|
||||||
@ -475,3 +481,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
|
||||||
|
@ -110,6 +110,7 @@ class WowImport(SongImport):
|
|||||||
self.title = file_name.rpartition(u'.')[0]
|
self.title = file_name.rpartition(u'.')[0]
|
||||||
songData = open(file, 'rb')
|
songData = open(file, 'rb')
|
||||||
if songData.read(19) != u'WoW File\nSong Words':
|
if songData.read(19) != u'WoW File\nSong Words':
|
||||||
|
self.log_error(file)
|
||||||
continue
|
continue
|
||||||
# Seek to byte which stores number of blocks in the song
|
# Seek to byte which stores number of blocks in the song
|
||||||
songData.seek(56)
|
songData.seek(56)
|
||||||
|
@ -233,6 +233,7 @@ class OpenLyrics(object):
|
|||||||
IMPLEMENTED_VERSION = u'0.7'
|
IMPLEMENTED_VERSION = u'0.7'
|
||||||
def __init__(self, manager):
|
def __init__(self, manager):
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
|
self.chord_regex = re.compile(u'<chord name=".*?"/>')
|
||||||
|
|
||||||
def song_to_xml(self, song):
|
def song_to_xml(self, song):
|
||||||
"""
|
"""
|
||||||
@ -317,7 +318,7 @@ class OpenLyrics(object):
|
|||||||
if xml[:5] == u'<?xml':
|
if xml[:5] == u'<?xml':
|
||||||
xml = xml[38:]
|
xml = xml[38:]
|
||||||
# Remove chords from xml.
|
# Remove chords from xml.
|
||||||
xml = re.compile(u'<chord name=".*?"/>').sub(u'', xml)
|
xml = self.chord_regex.sub(u'', xml)
|
||||||
song_xml = objectify.fromstring(xml)
|
song_xml = objectify.fromstring(xml)
|
||||||
if hasattr(song_xml, u'properties'):
|
if hasattr(song_xml, u'properties'):
|
||||||
properties = song_xml.properties
|
properties = song_xml.properties
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
; NOTE: The value of AppId uniquely identifies this application.
|
; NOTE: The value of AppId uniquely identifies this application.
|
||||||
; Do not use the same AppId value in installers for other applications.
|
; Do not use the same AppId value in installers for other applications.
|
||||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||||
AppId={{AA7699FA-B2D2-43F4-8A70-D497D03C9485}
|
AppID={{AA7699FA-B2D2-43F4-8A70-D497D03C9485}
|
||||||
AppName={#AppName}
|
AppName={#AppName}
|
||||||
AppVerName={#AppVerName}
|
AppVerName={#AppVerName}
|
||||||
AppPublisher={#AppPublisher}
|
AppPublisher={#AppPublisher}
|
||||||
@ -29,11 +29,12 @@ AllowNoIcons=true
|
|||||||
LicenseFile=LICENSE.txt
|
LicenseFile=LICENSE.txt
|
||||||
OutputDir=..\..\dist
|
OutputDir=..\..\dist
|
||||||
OutputBaseFilename=OpenLP-{#RealVersion}-setup
|
OutputBaseFilename=OpenLP-{#RealVersion}-setup
|
||||||
Compression=lzma
|
Compression=lzma/Max
|
||||||
SolidCompression=true
|
SolidCompression=true
|
||||||
SetupIconFile=OpenLP.ico
|
SetupIconFile=OpenLP.ico
|
||||||
WizardImageFile=WizImageBig.bmp
|
WizardImageFile=WizImageBig.bmp
|
||||||
WizardSmallImageFile=WizImageSmall.bmp
|
WizardSmallImageFile=WizImageSmall.bmp
|
||||||
|
ChangesAssociations=true
|
||||||
|
|
||||||
[Languages]
|
[Languages]
|
||||||
Name: english; MessagesFile: compiler:Default.isl
|
Name: english; MessagesFile: compiler:Default.isl
|
||||||
@ -79,6 +80,10 @@ Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\{#AppName}; Filenam
|
|||||||
Filename: {app}\{#AppExeName}; Description: {cm:LaunchProgram,{#AppName}}; Flags: nowait postinstall skipifsilent
|
Filename: {app}\{#AppExeName}; Description: {cm:LaunchProgram,{#AppName}}; Flags: nowait postinstall skipifsilent
|
||||||
|
|
||||||
[Registry]
|
[Registry]
|
||||||
|
Root: HKCR; Subkey: ".osz"; ValueType: string; ValueName: ""; ValueData: "OpenLP"; Flags: uninsdeletevalue
|
||||||
|
Root: HKCR; Subkey: "OpenLP"; ValueType: string; ValueName: ""; ValueData: "OpenLP Service"; Flags: uninsdeletekey
|
||||||
|
Root: HKCR; Subkey: "OpenLP\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\OpenLP.exe,0"
|
||||||
|
Root: HKCR; Subkey: "OpenLP\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\OpenLP.exe"" ""%1"""
|
||||||
|
|
||||||
[Code]
|
[Code]
|
||||||
function GetUninstallString(): String;
|
function GetUninstallString(): String;
|
||||||
|
Loading…
Reference in New Issue
Block a user