forked from openlp/openlp
r1235
This commit is contained in:
commit
84b252fe70
@ -28,8 +28,6 @@ Provide common toolbar handling for OpenLP
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
|
||||||
|
|
||||||
from openlp.core.lib import build_icon
|
from openlp.core.lib import build_icon
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -51,7 +49,8 @@ class OpenLPToolbar(QtGui.QToolBar):
|
|||||||
log.debug(u'Init done')
|
log.debug(u'Init done')
|
||||||
|
|
||||||
def addToolbarButton(self, title, icon, tooltip=None, slot=None,
|
def addToolbarButton(self, title, icon, tooltip=None, slot=None,
|
||||||
checkable=False):
|
checkable=False, shortcut=0, alternate=0,
|
||||||
|
context=QtCore.Qt.WidgetShortcut):
|
||||||
"""
|
"""
|
||||||
A method to help developers easily add a button to the toolbar.
|
A method to help developers easily add a button to the toolbar.
|
||||||
|
|
||||||
@ -72,6 +71,15 @@ class OpenLPToolbar(QtGui.QToolBar):
|
|||||||
``checkable``
|
``checkable``
|
||||||
If *True* the button has two, *off* and *on*, states. Default is
|
If *True* the button has two, *off* and *on*, states. Default is
|
||||||
*False*, which means the buttons has only one state.
|
*False*, which means the buttons has only one state.
|
||||||
|
|
||||||
|
``shortcut``
|
||||||
|
The primary shortcut for this action
|
||||||
|
|
||||||
|
``alternate``
|
||||||
|
The alternate shortcut for this action
|
||||||
|
|
||||||
|
``context``
|
||||||
|
Specify the context in which this shortcut is valid
|
||||||
"""
|
"""
|
||||||
newAction = None
|
newAction = None
|
||||||
if icon:
|
if icon:
|
||||||
@ -93,6 +101,8 @@ class OpenLPToolbar(QtGui.QToolBar):
|
|||||||
QtCore.QObject.connect(newAction,
|
QtCore.QObject.connect(newAction,
|
||||||
QtCore.SIGNAL(u'toggled(bool)'), slot)
|
QtCore.SIGNAL(u'toggled(bool)'), slot)
|
||||||
self.actions[title] = newAction
|
self.actions[title] = newAction
|
||||||
|
newAction.setShortcuts([shortcut, alternate])
|
||||||
|
newAction.setShortcutContext(context)
|
||||||
return newAction
|
return newAction
|
||||||
|
|
||||||
def addToolbarSeparator(self, handle):
|
def addToolbarSeparator(self, handle):
|
||||||
|
@ -54,45 +54,6 @@ class DisplayWidget(QtGui.QGraphicsView):
|
|||||||
QtGui.QGraphicsView.__init__(self)
|
QtGui.QGraphicsView.__init__(self)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.live = live
|
self.live = live
|
||||||
self.hotkey_map = {
|
|
||||||
QtCore.Qt.Key_Return: 'servicemanager_next_item',
|
|
||||||
QtCore.Qt.Key_Space: 'slidecontroller_live_next_noloop',
|
|
||||||
QtCore.Qt.Key_Enter: 'slidecontroller_live_next_noloop',
|
|
||||||
QtCore.Qt.Key_0: 'servicemanager_next_item',
|
|
||||||
QtCore.Qt.Key_Backspace: 'slidecontroller_live_previous_noloop'}
|
|
||||||
self.setStyleSheet(u'border: none;')
|
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
|
||||||
"""
|
|
||||||
Handle key events from display screen
|
|
||||||
"""
|
|
||||||
# Key events only needed for live
|
|
||||||
if not self.live:
|
|
||||||
return
|
|
||||||
if isinstance(event, QtGui.QKeyEvent):
|
|
||||||
# Here accept the event and do something
|
|
||||||
if event.key() == QtCore.Qt.Key_Up:
|
|
||||||
Receiver.send_message(u'slidecontroller_live_previous')
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_Down:
|
|
||||||
Receiver.send_message(u'slidecontroller_live_next')
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_PageUp:
|
|
||||||
Receiver.send_message(u'slidecontroller_live_first')
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_PageDown:
|
|
||||||
Receiver.send_message(u'slidecontroller_live_last')
|
|
||||||
event.accept()
|
|
||||||
elif event.key() in self.hotkey_map:
|
|
||||||
Receiver.send_message(self.hotkey_map[event.key()])
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_Escape:
|
|
||||||
self.setVisible(False)
|
|
||||||
self.videoStop()
|
|
||||||
event.accept()
|
|
||||||
event.ignore()
|
|
||||||
else:
|
|
||||||
event.ignore()
|
|
||||||
|
|
||||||
|
|
||||||
class MainDisplay(DisplayWidget):
|
class MainDisplay(DisplayWidget):
|
||||||
|
@ -49,34 +49,6 @@ class ServiceManagerList(QtGui.QTreeWidget):
|
|||||||
QtGui.QTreeWidget.__init__(self, parent)
|
QtGui.QTreeWidget.__init__(self, parent)
|
||||||
self.mainwindow = mainwindow
|
self.mainwindow = mainwindow
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
|
||||||
if isinstance(event, QtGui.QKeyEvent):
|
|
||||||
#here accept the event and do something
|
|
||||||
if event.key() == QtCore.Qt.Key_Enter:
|
|
||||||
self.mainwindow.makeLive()
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_Home:
|
|
||||||
self.mainwindow.onServiceTop()
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_End:
|
|
||||||
self.mainwindow.onServiceEnd()
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_PageUp:
|
|
||||||
self.mainwindow.onServiceUp()
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_PageDown:
|
|
||||||
self.mainwindow.onServiceDown()
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_Up:
|
|
||||||
self.mainwindow.onMoveSelectionUp()
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_Down:
|
|
||||||
self.mainwindow.onMoveSelectionDown()
|
|
||||||
event.accept()
|
|
||||||
event.ignore()
|
|
||||||
else:
|
|
||||||
event.ignore()
|
|
||||||
|
|
||||||
def mouseMoveEvent(self, event):
|
def mouseMoveEvent(self, event):
|
||||||
"""
|
"""
|
||||||
Drag and drop event does not care what data is selected
|
Drag and drop event does not care what data is selected
|
||||||
@ -178,50 +150,72 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.layout.addWidget(self.serviceManagerList)
|
self.layout.addWidget(self.serviceManagerList)
|
||||||
# Add the bottom toolbar
|
# Add the bottom toolbar
|
||||||
self.orderToolbar = OpenLPToolbar(self)
|
self.orderToolbar = OpenLPToolbar(self)
|
||||||
self.orderToolbar.addToolbarButton(
|
self.serviceManagerList.moveTop = self.orderToolbar.addToolbarButton(
|
||||||
translate('OpenLP.ServiceManager', 'Move to &top'),
|
translate('OpenLP.ServiceManager', 'Move to &top'),
|
||||||
u':/services/service_top.png',
|
u':/services/service_top.png',
|
||||||
translate('OpenLP.ServiceManager',
|
translate('OpenLP.ServiceManager',
|
||||||
'Move item to the top of the service.'),
|
'Move item to the top of the service.'),
|
||||||
self.onServiceTop)
|
self.onServiceTop, shortcut=QtCore.Qt.Key_Home)
|
||||||
self.orderToolbar.addToolbarButton(
|
self.serviceManagerList.moveUp = self.orderToolbar.addToolbarButton(
|
||||||
translate('OpenLP.ServiceManager', 'Move &up'),
|
translate('OpenLP.ServiceManager', 'Move &up'),
|
||||||
u':/services/service_up.png',
|
u':/services/service_up.png',
|
||||||
translate('OpenLP.ServiceManager',
|
translate('OpenLP.ServiceManager',
|
||||||
'Move item up one position in the service.'),
|
'Move item up one position in the service.'),
|
||||||
self.onServiceUp)
|
self.onServiceUp, shortcut=QtCore.Qt.Key_PageUp)
|
||||||
self.orderToolbar.addToolbarButton(
|
self.serviceManagerList.moveDown = self.orderToolbar.addToolbarButton(
|
||||||
translate('OpenLP.ServiceManager', 'Move &down'),
|
translate('OpenLP.ServiceManager', 'Move &down'),
|
||||||
u':/services/service_down.png',
|
u':/services/service_down.png',
|
||||||
translate('OpenLP.ServiceManager',
|
translate('OpenLP.ServiceManager',
|
||||||
'Move item down one position in the service.'),
|
'Move item down one position in the service.'),
|
||||||
self.onServiceDown)
|
self.onServiceDown, shortcut=QtCore.Qt.Key_PageDown)
|
||||||
self.orderToolbar.addToolbarButton(
|
self.serviceManagerList.moveBottom = self.orderToolbar.addToolbarButton(
|
||||||
translate('OpenLP.ServiceManager', 'Move to &bottom'),
|
translate('OpenLP.ServiceManager', 'Move to &bottom'),
|
||||||
u':/services/service_bottom.png',
|
u':/services/service_bottom.png',
|
||||||
translate('OpenLP.ServiceManager',
|
translate('OpenLP.ServiceManager',
|
||||||
'Move item to the end of the service.'),
|
'Move item to the end of the service.'),
|
||||||
self.onServiceEnd)
|
self.onServiceEnd, shortcut=QtCore.Qt.Key_End)
|
||||||
|
self.serviceManagerList.down = self.orderToolbar.addToolbarButton(
|
||||||
|
translate('OpenLP.ServiceManager', 'Move &down'),
|
||||||
|
None,
|
||||||
|
translate('OpenLP.ServiceManager',
|
||||||
|
'Moves the selection up the window.'),
|
||||||
|
self.onMoveSelectionDown, shortcut=QtCore.Qt.Key_Up)
|
||||||
|
self.serviceManagerList.down.setVisible(False)
|
||||||
|
self.serviceManagerList.up = self.orderToolbar.addToolbarButton(
|
||||||
|
translate('OpenLP.ServiceManager', 'Move up'),
|
||||||
|
None,
|
||||||
|
translate('OpenLP.ServiceManager',
|
||||||
|
'Moves the selection up the window.'),
|
||||||
|
self.onMoveSelectionUp, shortcut=QtCore.Qt.Key_Up)
|
||||||
|
self.serviceManagerList.up.setVisible(False)
|
||||||
self.orderToolbar.addSeparator()
|
self.orderToolbar.addSeparator()
|
||||||
self.orderToolbar.addToolbarButton(
|
self.serviceManagerList.delete = self.orderToolbar.addToolbarButton(
|
||||||
translate('OpenLP.ServiceManager', '&Delete From Service'),
|
translate('OpenLP.ServiceManager', '&Delete From Service'),
|
||||||
u':/general/general_delete.png',
|
u':/general/general_delete.png',
|
||||||
translate('OpenLP.ServiceManager',
|
translate('OpenLP.ServiceManager',
|
||||||
'Delete the selected item from the service.'),
|
'Delete the selected item from the service.'),
|
||||||
self.onDeleteFromService)
|
self.onDeleteFromService)
|
||||||
self.orderToolbar.addSeparator()
|
self.orderToolbar.addSeparator()
|
||||||
self.orderToolbar.addToolbarButton(
|
self.serviceManagerList.expand = self.orderToolbar.addToolbarButton(
|
||||||
translate('OpenLP.ServiceManager', '&Expand all'),
|
translate('OpenLP.ServiceManager', '&Expand all'),
|
||||||
u':/services/service_expand_all.png',
|
u':/services/service_expand_all.png',
|
||||||
translate('OpenLP.ServiceManager',
|
translate('OpenLP.ServiceManager',
|
||||||
'Expand all the service items.'),
|
'Expand all the service items.'),
|
||||||
self.onExpandAll)
|
self.onExpandAll)
|
||||||
self.orderToolbar.addToolbarButton(
|
self.serviceManagerList.collapse = self.orderToolbar.addToolbarButton(
|
||||||
translate('OpenLP.ServiceManager', '&Collapse all'),
|
translate('OpenLP.ServiceManager', '&Collapse all'),
|
||||||
u':/services/service_collapse_all.png',
|
u':/services/service_collapse_all.png',
|
||||||
translate('OpenLP.ServiceManager',
|
translate('OpenLP.ServiceManager',
|
||||||
'Collapse all the service items.'),
|
'Collapse all the service items.'),
|
||||||
self.onCollapseAll)
|
self.onCollapseAll)
|
||||||
|
self.orderToolbar.addSeparator()
|
||||||
|
self.serviceManagerList.makeLive = self.orderToolbar.addToolbarButton(
|
||||||
|
translate('OpenLP.ServiceManager', 'Go Live'),
|
||||||
|
u':/general/general_live.png',
|
||||||
|
translate('OpenLP.ServiceManager',
|
||||||
|
'Send the selected item to Live.'),
|
||||||
|
self.makeLive, shortcut=QtCore.Qt.Key_Enter,
|
||||||
|
alternate=QtCore.Qt.Key_Return)
|
||||||
self.orderToolbar.setObjectName(u'orderToolbar')
|
self.orderToolbar.setObjectName(u'orderToolbar')
|
||||||
self.layout.addWidget(self.orderToolbar)
|
self.layout.addWidget(self.orderToolbar)
|
||||||
# Connect up our signals and slots
|
# Connect up our signals and slots
|
||||||
@ -292,8 +286,28 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.themeMenu = QtGui.QMenu(
|
self.themeMenu = QtGui.QMenu(
|
||||||
translate('OpenLP.ServiceManager', '&Change Item Theme'))
|
translate('OpenLP.ServiceManager', '&Change Item Theme'))
|
||||||
self.menu.addMenu(self.themeMenu)
|
self.menu.addMenu(self.themeMenu)
|
||||||
|
self.setServiceHotkeys()
|
||||||
|
self.serviceManagerList.addActions(
|
||||||
|
[self.serviceManagerList.moveDown,
|
||||||
|
self.serviceManagerList.moveUp,
|
||||||
|
self.serviceManagerList.makeLive,
|
||||||
|
self.serviceManagerList.moveTop,
|
||||||
|
self.serviceManagerList.moveBottom,
|
||||||
|
self.serviceManagerList.up,
|
||||||
|
self.serviceManagerList.down
|
||||||
|
])
|
||||||
self.configUpdated()
|
self.configUpdated()
|
||||||
|
|
||||||
|
def setServiceHotkeys(self):
|
||||||
|
actionList = self.mainwindow.actionList
|
||||||
|
actionList.add_action(self.serviceManagerList.moveDown, u'Service')
|
||||||
|
actionList.add_action(self.serviceManagerList.moveUp, u'Service')
|
||||||
|
actionList.add_action(self.serviceManagerList.moveTop, u'Service')
|
||||||
|
actionList.add_action(self.serviceManagerList.moveBottom, u'Service')
|
||||||
|
actionList.add_action(self.serviceManagerList.makeLive, u'Service')
|
||||||
|
actionList.add_action(self.serviceManagerList.up, u'Service')
|
||||||
|
actionList.add_action(self.serviceManagerList.down, u'Service')
|
||||||
|
|
||||||
def setModified(self, modified=True):
|
def setModified(self, modified=True):
|
||||||
"""
|
"""
|
||||||
Setter for property "modified". Sets whether or not the current service
|
Setter for property "modified". Sets whether or not the current service
|
||||||
|
@ -33,6 +33,7 @@ from PyQt4.phonon import Phonon
|
|||||||
from openlp.core.ui import HideMode, MainDisplay
|
from openlp.core.ui import HideMode, MainDisplay
|
||||||
from openlp.core.lib import OpenLPToolbar, Receiver, resize_image, \
|
from openlp.core.lib import OpenLPToolbar, Receiver, resize_image, \
|
||||||
ItemCapabilities, translate
|
ItemCapabilities, translate
|
||||||
|
from openlp.core.utils import ActionList
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -44,34 +45,6 @@ class SlideList(QtGui.QTableWidget):
|
|||||||
def __init__(self, parent=None, name=None):
|
def __init__(self, parent=None, name=None):
|
||||||
QtGui.QTableWidget.__init__(self, parent.Controller)
|
QtGui.QTableWidget.__init__(self, parent.Controller)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.hotkeyMap = {
|
|
||||||
QtCore.Qt.Key_Return: 'servicemanager_next_item',
|
|
||||||
QtCore.Qt.Key_Space: 'slidecontroller_live_next_noloop',
|
|
||||||
QtCore.Qt.Key_Enter: 'slidecontroller_live_next_noloop',
|
|
||||||
QtCore.Qt.Key_0: 'servicemanager_next_item',
|
|
||||||
QtCore.Qt.Key_Backspace: 'slidecontroller_live_previous_noloop'}
|
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
|
||||||
if isinstance(event, QtGui.QKeyEvent):
|
|
||||||
#here accept the event and do something
|
|
||||||
if event.key() == QtCore.Qt.Key_Up:
|
|
||||||
self.parent.onSlideSelectedPrevious()
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_Down:
|
|
||||||
self.parent.onSlideSelectedNext()
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_PageUp:
|
|
||||||
self.parent.onSlideSelectedFirst()
|
|
||||||
event.accept()
|
|
||||||
elif event.key() == QtCore.Qt.Key_PageDown:
|
|
||||||
self.parent.onSlideSelectedLast()
|
|
||||||
event.accept()
|
|
||||||
elif event.key() in self.hotkeyMap and self.parent.isLive:
|
|
||||||
Receiver.send_message(self.hotkeyMap[event.key()])
|
|
||||||
event.accept()
|
|
||||||
event.ignore()
|
|
||||||
else:
|
|
||||||
event.ignore()
|
|
||||||
|
|
||||||
|
|
||||||
class SlideController(QtGui.QWidget):
|
class SlideController(QtGui.QWidget):
|
||||||
@ -162,12 +135,14 @@ class SlideController(QtGui.QWidget):
|
|||||||
sizeToolbarPolicy.setHeightForWidth(
|
sizeToolbarPolicy.setHeightForWidth(
|
||||||
self.Toolbar.sizePolicy().hasHeightForWidth())
|
self.Toolbar.sizePolicy().hasHeightForWidth())
|
||||||
self.Toolbar.setSizePolicy(sizeToolbarPolicy)
|
self.Toolbar.setSizePolicy(sizeToolbarPolicy)
|
||||||
self.Toolbar.addToolbarButton(
|
self.previousItem = self.Toolbar.addToolbarButton(
|
||||||
u'Previous Slide', u':/slides/slide_previous.png',
|
translate('OpenLP.SlideController', 'Previous Slide'),
|
||||||
|
u':/slides/slide_previous.png',
|
||||||
translate('OpenLP.SlideController', 'Move to previous'),
|
translate('OpenLP.SlideController', 'Move to previous'),
|
||||||
self.onSlideSelectedPrevious)
|
self.onSlideSelectedPrevious)
|
||||||
self.Toolbar.addToolbarButton(
|
self.nextItem = self.Toolbar.addToolbarButton(
|
||||||
u'Next Slide', u':/slides/slide_next.png',
|
translate('OpenLP.SlideController', 'Next Slide'),
|
||||||
|
u':/slides/slide_next.png',
|
||||||
translate('OpenLP.SlideController', 'Move to next'),
|
translate('OpenLP.SlideController', 'Move to next'),
|
||||||
self.onSlideSelectedNext)
|
self.onSlideSelectedNext)
|
||||||
if self.isLive:
|
if self.isLive:
|
||||||
@ -339,6 +314,25 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.onGoLiveClick)
|
self.onGoLiveClick)
|
||||||
self.Toolbar.makeWidgetsInvisible(self.songEditList)
|
self.Toolbar.makeWidgetsInvisible(self.songEditList)
|
||||||
self.Mediabar.setVisible(False)
|
self.Mediabar.setVisible(False)
|
||||||
|
if self.isLive:
|
||||||
|
self.setLiveHotkeys(self)
|
||||||
|
self.PreviewListWidget.addActions(
|
||||||
|
[self.previousItem,
|
||||||
|
self.nextItem,
|
||||||
|
self.previousService,
|
||||||
|
self.nextService,
|
||||||
|
self.escapeItem])
|
||||||
|
self.display.addActions(
|
||||||
|
[self.previousItem,
|
||||||
|
self.nextItem,
|
||||||
|
self.previousService,
|
||||||
|
self.nextService,
|
||||||
|
self.escapeItem])
|
||||||
|
else:
|
||||||
|
self.setPreviewHotkeys()
|
||||||
|
self.PreviewListWidget.addActions(
|
||||||
|
[self.nextItem,
|
||||||
|
self.previousItem])
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix),
|
QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix),
|
||||||
self.onStopLoop)
|
self.onStopLoop)
|
||||||
@ -379,6 +373,55 @@ class SlideController(QtGui.QWidget):
|
|||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'config_screen_changed'), self.screenSizeChanged)
|
QtCore.SIGNAL(u'config_screen_changed'), self.screenSizeChanged)
|
||||||
|
|
||||||
|
def setPreviewHotkeys(self, parent=None):
|
||||||
|
actionList = self.parent.actionList
|
||||||
|
self.previousItem.setShortcuts([QtCore.Qt.Key_Up, 0])
|
||||||
|
actionList.add_action(self.previousItem, u'Preview')
|
||||||
|
self.nextItem.setShortcuts([QtCore.Qt.Key_Down, 0])
|
||||||
|
actionList.add_action(self.nextItem, u'Preview')
|
||||||
|
|
||||||
|
def setLiveHotkeys(self, parent=None):
|
||||||
|
actionList = self.parent.actionList
|
||||||
|
self.previousItem.setShortcuts([QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp])
|
||||||
|
self.previousItem.setShortcutContext(
|
||||||
|
QtCore.Qt.WidgetWithChildrenShortcut)
|
||||||
|
actionList.add_action(self.nextItem, u'Live')
|
||||||
|
self.nextItem.setShortcuts([QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown])
|
||||||
|
self.nextItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
|
||||||
|
actionList.add_action(self.nextItem, u'Live')
|
||||||
|
self.previousService = QtGui.QAction(translate(
|
||||||
|
'OpenLP.SlideController', 'Previous Service'), parent)
|
||||||
|
self.previousService.setShortcuts([QtCore.Qt.Key_Left, 0])
|
||||||
|
self.previousService.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
|
||||||
|
QtCore.QObject.connect(self.previousService,
|
||||||
|
QtCore.SIGNAL(u'triggered()'), self.servicePrevious)
|
||||||
|
actionList.add_action(self.previousService, u'Live')
|
||||||
|
self.nextService = QtGui.QAction(translate(
|
||||||
|
'OpenLP.SlideController', 'Next Service'), parent)
|
||||||
|
self.nextService.setShortcuts([QtCore.Qt.Key_Right, 0])
|
||||||
|
self.nextService.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
|
||||||
|
QtCore.QObject.connect(self.nextService,
|
||||||
|
QtCore.SIGNAL(u'triggered()'), self.serviceNext)
|
||||||
|
actionList.add_action(self.nextService, u'Live')
|
||||||
|
self.escapeItem = QtGui.QAction(translate(
|
||||||
|
'OpenLP.SlideController', 'Escape Item'), parent)
|
||||||
|
self.escapeItem.setShortcuts([QtCore.Qt.Key_Escape, 0])
|
||||||
|
self.escapeItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
|
||||||
|
QtCore.QObject.connect(self.escapeItem,
|
||||||
|
QtCore.SIGNAL(u'triggered()'), self.liveEscape)
|
||||||
|
actionList.add_action(self.escapeItem, u'Live')
|
||||||
|
|
||||||
|
def liveEscape(self):
|
||||||
|
self.display.setVisible(False)
|
||||||
|
self.display.videoStop()
|
||||||
|
|
||||||
|
def servicePrevious(self):
|
||||||
|
Receiver.send_message('servicemanager_previous_item')
|
||||||
|
|
||||||
|
def serviceNext(self):
|
||||||
|
Receiver.send_message('servicemanager_next_item')
|
||||||
|
|
||||||
|
|
||||||
def screenSizeChanged(self):
|
def screenSizeChanged(self):
|
||||||
"""
|
"""
|
||||||
Settings dialog has changed the screen size of adjust output and
|
Settings dialog has changed the screen size of adjust output and
|
||||||
@ -389,6 +432,13 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.display.imageManager = self.parent.renderManager.image_manager
|
self.display.imageManager = self.parent.renderManager.image_manager
|
||||||
self.display.alertTab = self.alertTab
|
self.display.alertTab = self.alertTab
|
||||||
self.display.setup()
|
self.display.setup()
|
||||||
|
if self.isLive:
|
||||||
|
self.display.addActions(
|
||||||
|
[self.previousItem,
|
||||||
|
self.nextItem,
|
||||||
|
self.previousService,
|
||||||
|
self.nextService,
|
||||||
|
self.escapeItem])
|
||||||
# The SlidePreview's ratio.
|
# The SlidePreview's ratio.
|
||||||
self.ratio = float(self.screens.current[u'size'].width()) / \
|
self.ratio = float(self.screens.current[u'size'].width()) / \
|
||||||
float(self.screens.current[u'size'].height())
|
float(self.screens.current[u'size'].height())
|
||||||
@ -1071,4 +1121,3 @@ class SlideController(QtGui.QWidget):
|
|||||||
if self.DesktopScreen.isChecked:
|
if self.DesktopScreen.isChecked:
|
||||||
self.DesktopScreen.setChecked(False)
|
self.DesktopScreen.setChecked(False)
|
||||||
self.HideMenu.setDefaultAction(self.DesktopScreen)
|
self.HideMenu.setDefaultAction(self.DesktopScreen)
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
The :mod:`~openlp.core.utils.actions` module provides action list classes used
|
The :mod:`~openlp.core.utils.actions` module provides action list classes used
|
||||||
by the shortcuts system.
|
by the shortcuts system.
|
||||||
"""
|
"""
|
||||||
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
class ActionCategory(object):
|
class ActionCategory(object):
|
||||||
"""
|
"""
|
||||||
|
@ -109,7 +109,7 @@ def parse_reference(reference):
|
|||||||
regular expression looks like this:
|
regular expression looks like this:
|
||||||
|
|
||||||
1. ``^\s*(?!\s)(?P<book>[\d]*[^\d]+)(?<!\s)\s*``
|
1. ``^\s*(?!\s)(?P<book>[\d]*[^\d]+)(?<!\s)\s*``
|
||||||
The ``book`` group starts with the first non-whitespace character. There
|
The ``book`` group starts with the first non-whitespace character. There
|
||||||
are optional leading digits followed by non-digits. The group ends
|
are optional leading digits followed by non-digits. The group ends
|
||||||
before the whitspace in front of the next digit.
|
before the whitspace in front of the next digit.
|
||||||
2. ``(?P<ranges>(?:`` + range_string + ``(?:%(sep_l)s|(?=\s*$)))+)\s*$``
|
2. ``(?P<ranges>(?:`` + range_string + ``(?:%(sep_l)s|(?=\s*$)))+)\s*$``
|
||||||
@ -177,7 +177,7 @@ def parse_reference(reference):
|
|||||||
to_verse = -1
|
to_verse = -1
|
||||||
if to_chapter > from_chapter:
|
if to_chapter > from_chapter:
|
||||||
ref_list.append((book, from_chapter, from_verse, -1))
|
ref_list.append((book, from_chapter, from_verse, -1))
|
||||||
for i in range(from_chapter + 1, to_chapter - 1):
|
for i in range(from_chapter + 1, to_chapter):
|
||||||
ref_list.append((book, i, 1, -1))
|
ref_list.append((book, i, 1, -1))
|
||||||
ref_list.append((book, to_chapter, 1, to_verse))
|
ref_list.append((book, to_chapter, 1, to_verse))
|
||||||
elif to_verse >= from_verse or to_verse == -1:
|
elif to_verse >= from_verse or to_verse == -1:
|
||||||
|
@ -784,7 +784,6 @@ class SongImportForm(OpenLPWizard):
|
|||||||
filenames=self.getListOfFiles(self.songBeamerFileListWidget)
|
filenames=self.getListOfFiles(self.songBeamerFileListWidget)
|
||||||
)
|
)
|
||||||
if importer.do_import():
|
if importer.do_import():
|
||||||
# reload songs
|
|
||||||
self.progressLabel.setText(
|
self.progressLabel.setText(
|
||||||
translate('SongsPlugin.SongImportForm', 'Finished import.'))
|
translate('SongsPlugin.SongImportForm', 'Finished import.'))
|
||||||
else:
|
else:
|
||||||
|
@ -50,6 +50,14 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
self.authorform = AuthorsForm(self)
|
self.authorform = AuthorsForm(self)
|
||||||
self.topicform = TopicsForm(self)
|
self.topicform = TopicsForm(self)
|
||||||
self.bookform = SongBookForm(self)
|
self.bookform = SongBookForm(self)
|
||||||
|
# Disable all edit and delete buttons, as there is no row selected.
|
||||||
|
self.authorsDeleteButton.setEnabled(False)
|
||||||
|
self.authorsEditButton.setEnabled(False)
|
||||||
|
self.topicsDeleteButton.setEnabled(False)
|
||||||
|
self.topicsEditButton.setEnabled(False)
|
||||||
|
self.booksDeleteButton.setEnabled(False)
|
||||||
|
self.booksEditButton.setEnabled(False)
|
||||||
|
# Signals
|
||||||
QtCore.QObject.connect(self.authorsAddButton,
|
QtCore.QObject.connect(self.authorsAddButton,
|
||||||
QtCore.SIGNAL(u'pressed()'), self.onAuthorAddButtonClick)
|
QtCore.SIGNAL(u'pressed()'), self.onAuthorAddButtonClick)
|
||||||
QtCore.QObject.connect(self.topicsAddButton,
|
QtCore.QObject.connect(self.topicsAddButton,
|
||||||
@ -68,6 +76,15 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
QtCore.SIGNAL(u'pressed()'), self.onTopicDeleteButtonClick)
|
QtCore.SIGNAL(u'pressed()'), self.onTopicDeleteButtonClick)
|
||||||
QtCore.QObject.connect(self.booksDeleteButton,
|
QtCore.QObject.connect(self.booksDeleteButton,
|
||||||
QtCore.SIGNAL(u'pressed()'), self.onBookDeleteButtonClick)
|
QtCore.SIGNAL(u'pressed()'), self.onBookDeleteButtonClick)
|
||||||
|
QtCore.QObject.connect(self.authorsListWidget,
|
||||||
|
QtCore.SIGNAL(u'currentRowChanged(int)'),
|
||||||
|
self.onAuthorsListRowChanged)
|
||||||
|
QtCore.QObject.connect(self.topicsListWidget,
|
||||||
|
QtCore.SIGNAL(u'currentRowChanged(int)'),
|
||||||
|
self.onTopicsListRowChanged)
|
||||||
|
QtCore.QObject.connect(self.booksListWidget,
|
||||||
|
QtCore.SIGNAL(u'currentRowChanged(int)'),
|
||||||
|
self.onBooksListRowChanged)
|
||||||
|
|
||||||
def exec_(self):
|
def exec_(self):
|
||||||
self.typeListWidget.setCurrentRow(0)
|
self.typeListWidget.setCurrentRow(0)
|
||||||
@ -115,12 +132,6 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
u' '.join([author.first_name, author.last_name]))
|
u' '.join([author.first_name, author.last_name]))
|
||||||
author_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(author.id))
|
author_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(author.id))
|
||||||
self.authorsListWidget.addItem(author_name)
|
self.authorsListWidget.addItem(author_name)
|
||||||
if self.authorsListWidget.count() == 0:
|
|
||||||
self.authorsDeleteButton.setEnabled(False)
|
|
||||||
self.authorsEditButton.setEnabled(False)
|
|
||||||
else:
|
|
||||||
self.authorsDeleteButton.setEnabled(True)
|
|
||||||
self.authorsEditButton.setEnabled(True)
|
|
||||||
|
|
||||||
def resetTopics(self):
|
def resetTopics(self):
|
||||||
"""
|
"""
|
||||||
@ -132,12 +143,6 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
topic_name = QtGui.QListWidgetItem(topic.name)
|
topic_name = QtGui.QListWidgetItem(topic.name)
|
||||||
topic_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id))
|
topic_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id))
|
||||||
self.topicsListWidget.addItem(topic_name)
|
self.topicsListWidget.addItem(topic_name)
|
||||||
if self.topicsListWidget.count() == 0:
|
|
||||||
self.topicsDeleteButton.setEnabled(False)
|
|
||||||
self.topicsEditButton.setEnabled(False)
|
|
||||||
else:
|
|
||||||
self.topicsDeleteButton.setEnabled(True)
|
|
||||||
self.topicsEditButton.setEnabled(True)
|
|
||||||
|
|
||||||
def resetBooks(self):
|
def resetBooks(self):
|
||||||
"""
|
"""
|
||||||
@ -150,26 +155,22 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
book.publisher))
|
book.publisher))
|
||||||
book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id))
|
book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id))
|
||||||
self.booksListWidget.addItem(book_name)
|
self.booksListWidget.addItem(book_name)
|
||||||
if self.booksListWidget.count() == 0:
|
|
||||||
self.booksDeleteButton.setEnabled(False)
|
|
||||||
self.booksEditButton.setEnabled(False)
|
|
||||||
else:
|
|
||||||
self.booksDeleteButton.setEnabled(True)
|
|
||||||
self.booksEditButton.setEnabled(True)
|
|
||||||
|
|
||||||
def checkAuthor(self, new_author, edit=False):
|
def checkAuthor(self, new_author, edit=False):
|
||||||
"""
|
"""
|
||||||
Returns False if the given Author is already in the list otherwise
|
Returns *False* if the given Author already exists, otherwise *True*.
|
||||||
True.
|
|
||||||
|
``edit``
|
||||||
|
If we edit an item, this should be *True*.
|
||||||
"""
|
"""
|
||||||
authors = self.manager.get_all_objects(Author,
|
authors = self.manager.get_all_objects(Author,
|
||||||
and_(Author.first_name == new_author.first_name,
|
and_(Author.first_name == new_author.first_name,
|
||||||
Author.last_name == new_author.last_name,
|
Author.last_name == new_author.last_name,
|
||||||
Author.display_name == new_author.display_name))
|
Author.display_name == new_author.display_name))
|
||||||
|
# Check if this author already exists.
|
||||||
if len(authors) > 0:
|
if len(authors) > 0:
|
||||||
# If we edit an existing Author, we need to make sure that we do
|
# If we edit an existing Author, we need to make sure that we do
|
||||||
# not return False when nothing has changed (because this would
|
# not return False when nothing has changed.
|
||||||
# cause an error message later on).
|
|
||||||
if edit:
|
if edit:
|
||||||
for author in authors:
|
for author in authors:
|
||||||
if author.id != new_author.id:
|
if author.id != new_author.id:
|
||||||
@ -182,14 +183,16 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
|
|
||||||
def checkTopic(self, new_topic, edit=False):
|
def checkTopic(self, new_topic, edit=False):
|
||||||
"""
|
"""
|
||||||
Returns False if the given Topic is already in the list otherwise True.
|
Returns *False* if the given Topic already exists, otherwise *True*.
|
||||||
|
|
||||||
|
``edit``
|
||||||
|
If we edit an item, this should be *True*.
|
||||||
"""
|
"""
|
||||||
topics = self.manager.get_all_objects(Topic,
|
topics = self.manager.get_all_objects(Topic,
|
||||||
Topic.name == new_topic.name)
|
Topic.name == new_topic.name)
|
||||||
if len(topics) > 0:
|
if len(topics) > 0:
|
||||||
# If we edit an existing Topic, we need to make sure that we do
|
# If we edit an existing Topic, we need to make sure that we do
|
||||||
# not return False when nothing has changed (because this would
|
# not return False when nothing has changed.
|
||||||
# cause an error message later on).
|
|
||||||
if edit:
|
if edit:
|
||||||
for topic in topics:
|
for topic in topics:
|
||||||
if topic.id != new_topic.id:
|
if topic.id != new_topic.id:
|
||||||
@ -202,15 +205,17 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
|
|
||||||
def checkBook(self, new_book, edit=False):
|
def checkBook(self, new_book, edit=False):
|
||||||
"""
|
"""
|
||||||
Returns False if the given Book is already in the list otherwise True.
|
Returns *False* if the given Topic already exists, otherwise *True*.
|
||||||
|
|
||||||
|
``edit``
|
||||||
|
If we edit an item, this should be *True*.
|
||||||
"""
|
"""
|
||||||
books = self.manager.get_all_objects(Book,
|
books = self.manager.get_all_objects(Book,
|
||||||
and_(Book.name == new_book.name,
|
and_(Book.name == new_book.name,
|
||||||
Book.publisher == new_book.publisher))
|
Book.publisher == new_book.publisher))
|
||||||
if len(books) > 0:
|
if len(books) > 0:
|
||||||
# If we edit an existing Book, we need to make sure that we do
|
# If we edit an existing Book, we need to make sure that we do
|
||||||
# not return False when nothing has changed (because this would
|
# not return False when nothing has changed.
|
||||||
# cause an error message later on).
|
|
||||||
if edit:
|
if edit:
|
||||||
for book in books:
|
for book in books:
|
||||||
if book.id != new_book.id:
|
if book.id != new_book.id:
|
||||||
@ -390,12 +395,14 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
Merges two authors into one author.
|
Merges two authors into one author.
|
||||||
|
|
||||||
``old_author``
|
``old_author``
|
||||||
The author which will be deleted afterwards.
|
The object, which was edited, that will be deleted
|
||||||
"""
|
"""
|
||||||
|
# Find the duplicate.
|
||||||
existing_author = self.manager.get_object_filtered(Author,
|
existing_author = self.manager.get_object_filtered(Author,
|
||||||
and_(Author.first_name == old_author.first_name,
|
and_(Author.first_name == old_author.first_name,
|
||||||
Author.last_name == old_author.last_name,
|
Author.last_name == old_author.last_name,
|
||||||
Author.display_name == old_author.display_name))
|
Author.display_name == old_author.display_name))
|
||||||
|
# Find the songs, which have the old_author as author.
|
||||||
songs = self.manager.get_all_objects(Song,
|
songs = self.manager.get_all_objects(Song,
|
||||||
Song.authors.contains(old_author))
|
Song.authors.contains(old_author))
|
||||||
for song in songs:
|
for song in songs:
|
||||||
@ -412,10 +419,12 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
Merges two topics into one topic.
|
Merges two topics into one topic.
|
||||||
|
|
||||||
``old_topic``
|
``old_topic``
|
||||||
The topic which will be deleted afterwards.
|
The object, which was edited, that will be deleted
|
||||||
"""
|
"""
|
||||||
|
# Find the duplicate.
|
||||||
existing_topic = self.manager.get_object_filtered(Topic,
|
existing_topic = self.manager.get_object_filtered(Topic,
|
||||||
Topic.name == old_topic.name)
|
Topic.name == old_topic.name)
|
||||||
|
# Find the songs, which have the old_topic as topic.
|
||||||
songs = self.manager.get_all_objects(Song,
|
songs = self.manager.get_all_objects(Song,
|
||||||
Song.topics.contains(old_topic))
|
Song.topics.contains(old_topic))
|
||||||
for song in songs:
|
for song in songs:
|
||||||
@ -432,11 +441,13 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
Merges two books into one book.
|
Merges two books into one book.
|
||||||
|
|
||||||
``old_book``
|
``old_book``
|
||||||
The book which will be deleted afterwards.
|
The object, which was edited, that will be deleted
|
||||||
"""
|
"""
|
||||||
|
# Find the duplicate.
|
||||||
existing_book = self.manager.get_object_filtered(Book,
|
existing_book = self.manager.get_object_filtered(Book,
|
||||||
and_(Book.name == old_book.name,
|
and_(Book.name == old_book.name,
|
||||||
Book.publisher == old_book.publisher))
|
Book.publisher == old_book.publisher))
|
||||||
|
# Find the songs, which have the old_book as book.
|
||||||
songs = self.manager.get_all_objects(Song,
|
songs = self.manager.get_all_objects(Song,
|
||||||
Song.song_book_id == old_book.id)
|
Song.song_book_id == old_book.id)
|
||||||
for song in songs:
|
for song in songs:
|
||||||
@ -482,3 +493,46 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
'This book cannot be deleted, it is currently '
|
'This book cannot be deleted, it is currently '
|
||||||
'assigned to at least one song.'),
|
'assigned to at least one song.'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm', 'No book selected!'))
|
translate('SongsPlugin.SongMaintenanceForm', 'No book selected!'))
|
||||||
|
|
||||||
|
def onAuthorsListRowChanged(self, row):
|
||||||
|
"""
|
||||||
|
Called when the *authorsListWidget* current's row has changed.
|
||||||
|
|
||||||
|
``row``
|
||||||
|
The current row. If there is no current row, the value is -1
|
||||||
|
"""
|
||||||
|
if row == -1:
|
||||||
|
self.authorsDeleteButton.setEnabled(False)
|
||||||
|
self.authorsEditButton.setEnabled(False)
|
||||||
|
else:
|
||||||
|
self.authorsDeleteButton.setEnabled(True)
|
||||||
|
self.authorsEditButton.setEnabled(True)
|
||||||
|
|
||||||
|
def onTopicsListRowChanged(self, row):
|
||||||
|
"""
|
||||||
|
Called when the *booksListWidget* current's row has changed.
|
||||||
|
|
||||||
|
``row``
|
||||||
|
The current row. If there is no current row, the value is -1.
|
||||||
|
"""
|
||||||
|
if row == -1:
|
||||||
|
self.topicsDeleteButton.setEnabled(False)
|
||||||
|
self.topicsEditButton.setEnabled(False)
|
||||||
|
else:
|
||||||
|
self.topicsDeleteButton.setEnabled(True)
|
||||||
|
self.topicsEditButton.setEnabled(True)
|
||||||
|
|
||||||
|
def onBooksListRowChanged(self, row):
|
||||||
|
"""
|
||||||
|
Called when the *booksListWidget* current's row has changed.
|
||||||
|
|
||||||
|
``row``
|
||||||
|
The current row. If there is no current row, the value is -1.
|
||||||
|
"""
|
||||||
|
if row == -1:
|
||||||
|
self.booksDeleteButton.setEnabled(False)
|
||||||
|
self.booksEditButton.setEnabled(False)
|
||||||
|
else:
|
||||||
|
self.booksDeleteButton.setEnabled(True)
|
||||||
|
self.booksEditButton.setEnabled(True)
|
||||||
|
|
||||||
|
@ -313,7 +313,6 @@ class EasiSlidesImport(SongImport):
|
|||||||
tag = SeqTypes[tag.lower()]
|
tag = SeqTypes[tag.lower()]
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if tag in versetags:
|
if tag in versetags:
|
||||||
self.verse_order_list.append(tag)
|
self.verse_order_list.append(tag)
|
||||||
else:
|
else:
|
||||||
|
@ -157,7 +157,6 @@ class SongMediaItem(MediaManagerItem):
|
|||||||
(5, u':/slides/slide_theme.png',
|
(5, u':/slides/slide_theme.png',
|
||||||
translate('SongsPlugin.MediaItem', 'Themes'))
|
translate('SongsPlugin.MediaItem', 'Themes'))
|
||||||
])
|
])
|
||||||
|
|
||||||
self.configUpdated()
|
self.configUpdated()
|
||||||
|
|
||||||
def onSearchTextButtonClick(self):
|
def onSearchTextButtonClick(self):
|
||||||
@ -269,8 +268,8 @@ class SongMediaItem(MediaManagerItem):
|
|||||||
def onImportClick(self):
|
def onImportClick(self):
|
||||||
if not hasattr(self, u'import_wizard'):
|
if not hasattr(self, u'import_wizard'):
|
||||||
self.import_wizard = SongImportForm(self, self.parent)
|
self.import_wizard = SongImportForm(self, self.parent)
|
||||||
self.import_wizard.exec_()
|
if self.import_wizard.exec_() == QtGui.QDialog.Accepted:
|
||||||
Receiver.send_message(u'songs_load_list')
|
Receiver.send_message(u'songs_load_list')
|
||||||
|
|
||||||
def onNewClick(self):
|
def onNewClick(self):
|
||||||
log.debug(u'onNewClick')
|
log.debug(u'onNewClick')
|
||||||
|
@ -61,17 +61,18 @@ class OpenLyricsImport(SongImport):
|
|||||||
Imports the songs.
|
Imports the songs.
|
||||||
"""
|
"""
|
||||||
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
||||||
|
parser = etree.XMLParser(remove_blank_text=True)
|
||||||
for file_path in self.import_source:
|
for file_path in self.import_source:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return False
|
return False
|
||||||
self.import_wizard.incrementProgressBar(unicode(translate(
|
self.import_wizard.incrementProgressBar(unicode(translate(
|
||||||
'SongsPlugin.OpenLyricsImport', 'Importing %s...')) %
|
'SongsPlugin.OpenLyricsImport', 'Importing %s...')) %
|
||||||
os.path.basename(file_path))
|
os.path.basename(file_path))
|
||||||
parser = etree.XMLParser(remove_blank_text=True)
|
try:
|
||||||
parsed_file = etree.parse(file_path, parser)
|
parsed_file = etree.parse(file_path, parser)
|
||||||
xml = unicode(etree.tostring(parsed_file))
|
xml = unicode(etree.tostring(parsed_file))
|
||||||
if self.openLyrics.xml_to_song(xml) is None:
|
if self.openLyrics.xml_to_song(xml) is None:
|
||||||
log.debug(u'File could not be imported: %s' % file_path)
|
log.debug(u'File could not be imported: %s' % file_path)
|
||||||
# Importing this song failed! For now we stop import.
|
except etree.XMLSyntaxError:
|
||||||
return False
|
log.exception(u'XML syntax error in file %s' % file_path)
|
||||||
return True
|
return True
|
||||||
|
@ -197,16 +197,24 @@ class SongImport(QtCore.QObject):
|
|||||||
return
|
return
|
||||||
self.media_files.append(filename)
|
self.media_files.append(filename)
|
||||||
|
|
||||||
def add_verse(self, verse, versetag=u'V'):
|
def add_verse(self, versetext, versetag=u'V', lang=None):
|
||||||
"""
|
"""
|
||||||
Add a verse. This is the whole verse, lines split by \n
|
Add a verse. This is the whole verse, lines split by \n. It will also
|
||||||
Verse tag can be V1/C1/B etc, or 'V' and 'C' (will count the verses/
|
attempt to detect duplicates. In this case it will just add to the verse
|
||||||
choruses itself) or None, where it will assume verse
|
order.
|
||||||
It will also attempt to detect duplicates. In this case it will just
|
|
||||||
add to the verse order
|
``versetext``
|
||||||
|
The text of the verse.
|
||||||
|
|
||||||
|
``versetag``
|
||||||
|
The verse tag can be V1/C1/B etc, or 'V' and 'C' (will count the
|
||||||
|
verses/choruses itself) or None, where it will assume verse.
|
||||||
|
|
||||||
|
``lang``
|
||||||
|
The language code (ISO-639) of the verse, for example *en* or *de*.
|
||||||
"""
|
"""
|
||||||
for (oldversetag, oldverse) in self.verses:
|
for (oldversetag, oldverse, oldlang) in self.verses:
|
||||||
if oldverse.strip() == verse.strip():
|
if oldverse.strip() == versetext.strip():
|
||||||
self.verse_order_list.append(oldversetag)
|
self.verse_order_list.append(oldversetag)
|
||||||
return
|
return
|
||||||
if versetag[0] in self.versecounts:
|
if versetag[0] in self.versecounts:
|
||||||
@ -217,7 +225,7 @@ class SongImport(QtCore.QObject):
|
|||||||
versetag += unicode(self.versecounts[versetag[0]])
|
versetag += unicode(self.versecounts[versetag[0]])
|
||||||
elif int(versetag[1:]) > self.versecounts[versetag[0]]:
|
elif int(versetag[1:]) > self.versecounts[versetag[0]]:
|
||||||
self.versecounts[versetag[0]] = int(versetag[1:])
|
self.versecounts[versetag[0]] = int(versetag[1:])
|
||||||
self.verses.append([versetag, verse.rstrip()])
|
self.verses.append([versetag, versetext.rstrip(), lang])
|
||||||
self.verse_order_list.append(versetag)
|
self.verse_order_list.append(versetag)
|
||||||
if versetag.startswith(u'V') and self.contains_verse(u'C1'):
|
if versetag.startswith(u'V') and self.contains_verse(u'C1'):
|
||||||
self.verse_order_list.append(u'C1')
|
self.verse_order_list.append(u'C1')
|
||||||
@ -266,7 +274,7 @@ class SongImport(QtCore.QObject):
|
|||||||
verses_changed_to_other = {}
|
verses_changed_to_other = {}
|
||||||
sxml = SongXML()
|
sxml = SongXML()
|
||||||
other_count = 1
|
other_count = 1
|
||||||
for (versetag, versetext) in self.verses:
|
for (versetag, versetext, lang) in self.verses:
|
||||||
if versetag[0] == u'C':
|
if versetag[0] == u'C':
|
||||||
versetype = VerseType.to_string(VerseType.Chorus)
|
versetype = VerseType.to_string(VerseType.Chorus)
|
||||||
elif versetag[0] == u'V':
|
elif versetag[0] == u'V':
|
||||||
@ -286,7 +294,7 @@ class SongImport(QtCore.QObject):
|
|||||||
versetype = VerseType.to_string(VerseType.Other)
|
versetype = VerseType.to_string(VerseType.Other)
|
||||||
log.info(u'Versetype %s changing to %s' , versetag, newversetag)
|
log.info(u'Versetype %s changing to %s' , versetag, newversetag)
|
||||||
versetag = newversetag
|
versetag = newversetag
|
||||||
sxml.add_verse_to_lyrics(versetype, versetag[1:], versetext)
|
sxml.add_verse_to_lyrics(versetype, versetag[1:], versetext, lang)
|
||||||
song.search_lyrics += u' ' + self.remove_punctuation(versetext)
|
song.search_lyrics += u' ' + self.remove_punctuation(versetext)
|
||||||
song.search_lyrics = song.search_lyrics.lower()
|
song.search_lyrics = song.search_lyrics.lower()
|
||||||
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
||||||
@ -338,7 +346,7 @@ class SongImport(QtCore.QObject):
|
|||||||
+ u'========================================'
|
+ u'========================================'
|
||||||
print u'TITLE: ' + self.title
|
print u'TITLE: ' + self.title
|
||||||
print u'ALT TITLE: ' + self.alternate_title
|
print u'ALT TITLE: ' + self.alternate_title
|
||||||
for (versetag, versetext) in self.verses:
|
for (versetag, versetext, lang) in self.verses:
|
||||||
print u'VERSE ' + versetag + u': ' + versetext
|
print u'VERSE ' + versetag + u': ' + versetext
|
||||||
print u'ORDER: ' + u' '.join(self.verse_order_list)
|
print u'ORDER: ' + u' '.join(self.verse_order_list)
|
||||||
for author in self.authors:
|
for author in self.authors:
|
||||||
|
@ -31,7 +31,7 @@ The basic XML for storing the lyrics in the song database is of the format::
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<song version="1.0">
|
<song version="1.0">
|
||||||
<lyrics>
|
<lyrics>
|
||||||
<verse type="chorus" label="1">
|
<verse type="Chorus" label="1" lang="en">
|
||||||
<![CDATA[ ... ]]>
|
<![CDATA[ ... ]]>
|
||||||
</verse>
|
</verse>
|
||||||
</lyrics>
|
</lyrics>
|
||||||
@ -84,7 +84,7 @@ class SongXML(object):
|
|||||||
self.song_xml = objectify.fromstring(u'<song version="1.0" />')
|
self.song_xml = objectify.fromstring(u'<song version="1.0" />')
|
||||||
self.lyrics = etree.SubElement(self.song_xml, u'lyrics')
|
self.lyrics = etree.SubElement(self.song_xml, u'lyrics')
|
||||||
|
|
||||||
def add_verse_to_lyrics(self, type, number, content):
|
def add_verse_to_lyrics(self, type, number, content, lang=None):
|
||||||
"""
|
"""
|
||||||
Add a verse to the *<lyrics>* tag.
|
Add a verse to the *<lyrics>* tag.
|
||||||
|
|
||||||
@ -97,9 +97,15 @@ class SongXML(object):
|
|||||||
|
|
||||||
``content``
|
``content``
|
||||||
The actual text of the verse to be stored.
|
The actual text of the verse to be stored.
|
||||||
|
|
||||||
|
``lang``
|
||||||
|
The verse's language code (ISO-639). This is not required, but
|
||||||
|
should be added if available.
|
||||||
"""
|
"""
|
||||||
verse = etree.Element(u'verse', type=unicode(type),
|
verse = etree.Element(u'verse', type=unicode(type),
|
||||||
label=unicode(number))
|
label=unicode(number))
|
||||||
|
if lang:
|
||||||
|
verse.set(u'lang', lang)
|
||||||
verse.text = etree.CDATA(content)
|
verse.text = etree.CDATA(content)
|
||||||
self.lyrics.append(verse)
|
self.lyrics.append(verse)
|
||||||
|
|
||||||
@ -117,6 +123,11 @@ class SongXML(object):
|
|||||||
|
|
||||||
``xml``
|
``xml``
|
||||||
The XML of the song to be parsed.
|
The XML of the song to be parsed.
|
||||||
|
|
||||||
|
The returned list has the following format::
|
||||||
|
|
||||||
|
[[{'lang': 'en', 'type': 'V', 'label': '1'}, u"The English verse."],
|
||||||
|
[{'lang': 'en', 'type': 'C', 'label': '1'}, u"The English chorus."]]
|
||||||
"""
|
"""
|
||||||
self.song_xml = None
|
self.song_xml = None
|
||||||
if xml[:5] == u'<?xml':
|
if xml[:5] == u'<?xml':
|
||||||
@ -196,7 +207,7 @@ class OpenLyrics(object):
|
|||||||
This property is not supported.
|
This property is not supported.
|
||||||
|
|
||||||
*<verse name="v1a" lang="he" translit="en">*
|
*<verse name="v1a" lang="he" translit="en">*
|
||||||
The attribute *translit* and *lang* are not supported.
|
The attribute *translit* is not supported.
|
||||||
|
|
||||||
*<verseOrder>*
|
*<verseOrder>*
|
||||||
OpenLP supports this property.
|
OpenLP supports this property.
|
||||||
@ -268,13 +279,16 @@ class OpenLyrics(object):
|
|||||||
# No xml get out of here.
|
# No xml get out of here.
|
||||||
if not xml:
|
if not xml:
|
||||||
return None
|
return None
|
||||||
song = Song()
|
|
||||||
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 = re.compile(u'<chord name=".*?"/>').sub(u'', xml)
|
||||||
song_xml = objectify.fromstring(xml)
|
song_xml = objectify.fromstring(xml)
|
||||||
properties = song_xml.properties
|
try:
|
||||||
|
properties = song_xml.properties
|
||||||
|
except AttributeError:
|
||||||
|
return None
|
||||||
|
song = Song()
|
||||||
self._process_copyright(properties, song)
|
self._process_copyright(properties, song)
|
||||||
self._process_cclinumber(properties, song)
|
self._process_cclinumber(properties, song)
|
||||||
self._process_titles(properties, song)
|
self._process_titles(properties, song)
|
||||||
@ -442,7 +456,10 @@ class OpenLyrics(object):
|
|||||||
if not verse_number:
|
if not verse_number:
|
||||||
verse_number = u'1'
|
verse_number = u'1'
|
||||||
temp_verse_order.append((verse_type, verse_number, verse_part))
|
temp_verse_order.append((verse_type, verse_number, verse_part))
|
||||||
sxml.add_verse_to_lyrics(verse_type, verse_number, text)
|
lang = None
|
||||||
|
if self._get(verse, u'lang'):
|
||||||
|
lang = self._get(verse, u'lang')
|
||||||
|
sxml.add_verse_to_lyrics(verse_type, verse_number, text, lang)
|
||||||
search_text = search_text + text
|
search_text = search_text + text
|
||||||
song.search_lyrics = search_text.lower()
|
song.search_lyrics = search_text.lower()
|
||||||
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
||||||
|
@ -134,7 +134,7 @@ class SongsPlugin(Plugin):
|
|||||||
|
|
||||||
def onToolsReindexItemTriggered(self):
|
def onToolsReindexItemTriggered(self):
|
||||||
"""
|
"""
|
||||||
Rebuild the search title of each song.
|
Rebuild each song.
|
||||||
"""
|
"""
|
||||||
maxSongs = self.manager.get_object_count(Song)
|
maxSongs = self.manager.get_object_count(Song)
|
||||||
progressDialog = QtGui.QProgressDialog(
|
progressDialog = QtGui.QProgressDialog(
|
||||||
@ -150,8 +150,13 @@ class SongsPlugin(Plugin):
|
|||||||
song.title = u''
|
song.title = u''
|
||||||
if song.alternate_title is None:
|
if song.alternate_title is None:
|
||||||
song.alternate_title = u''
|
song.alternate_title = u''
|
||||||
song.search_title = self.whitespace.sub(u' ', song.title.lower() + \
|
song.search_title = self.whitespace.sub(u' ', song.title.lower() +
|
||||||
u' ' + song.alternate_title.lower())
|
u' ' + song.alternate_title.lower())
|
||||||
|
# Remove the "language" attribute from lyrics tag. This is not very
|
||||||
|
# important, but this keeps the database clean. This can be removed
|
||||||
|
# when everybody has run the reindex tool once.
|
||||||
|
song.lyrics = song.lyrics.replace(
|
||||||
|
u'<lyrics language="en">', u'<lyrics>')
|
||||||
lyrics = u''
|
lyrics = u''
|
||||||
verses = SongXML().get_verses(song.lyrics)
|
verses = SongXML().get_verses(song.lyrics)
|
||||||
for verse in verses:
|
for verse in verses:
|
||||||
@ -159,8 +164,7 @@ class SongsPlugin(Plugin):
|
|||||||
song.search_lyrics = lyrics.lower()
|
song.search_lyrics = lyrics.lower()
|
||||||
progressDialog.setValue(counter)
|
progressDialog.setValue(counter)
|
||||||
self.manager.save_objects(songs)
|
self.manager.save_objects(songs)
|
||||||
counter += 1
|
progressDialog.setValue(counter + 1)
|
||||||
progressDialog.setValue(counter)
|
|
||||||
self.mediaItem.displayResultsSong(
|
self.mediaItem.displayResultsSong(
|
||||||
self.manager.get_all_objects(Song, order_by_ref=Song.search_title))
|
self.manager.get_all_objects(Song, order_by_ref=Song.search_title))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user