forked from openlp/openlp
HEAD
This commit is contained in:
commit
8c916254e4
@ -1 +1 @@
|
|||||||
2.0
|
2.1.0-bzr2141
|
||||||
|
@ -34,7 +34,6 @@ import logging
|
|||||||
import os
|
import os
|
||||||
from urllib import quote_plus as urlquote
|
from urllib import quote_plus as urlquote
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
|
||||||
from sqlalchemy import Table, MetaData, Column, types, create_engine
|
from sqlalchemy import Table, MetaData, Column, types, create_engine
|
||||||
from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError, OperationalError
|
from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError, OperationalError
|
||||||
from sqlalchemy.orm import scoped_session, sessionmaker, mapper
|
from sqlalchemy.orm import scoped_session, sessionmaker, mapper
|
||||||
|
@ -31,8 +31,6 @@ Provide HTML Tag management and Formatting Tag access class
|
|||||||
"""
|
"""
|
||||||
import cPickle
|
import cPickle
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
|
||||||
|
|
||||||
from openlp.core.lib import translate, Settings
|
from openlp.core.lib import translate, Settings
|
||||||
|
|
||||||
class FormattingTags(object):
|
class FormattingTags(object):
|
||||||
|
@ -37,7 +37,9 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from openlp.core.lib import build_icon, clean_tags, expand_tags, translate, ImageSource
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
|
from openlp.core.lib import build_icon, clean_tags, expand_tags, translate, ImageSource, Settings
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -182,6 +184,7 @@ class ServiceItem(object):
|
|||||||
self.theme_overwritten = False
|
self.theme_overwritten = False
|
||||||
self.temporary_edit = False
|
self.temporary_edit = False
|
||||||
self.will_auto_start = False
|
self.will_auto_start = False
|
||||||
|
self.has_original_files = True
|
||||||
self._new_item()
|
self._new_item()
|
||||||
|
|
||||||
def _new_item(self):
|
def _new_item(self):
|
||||||
@ -190,6 +193,7 @@ class ServiceItem(object):
|
|||||||
service items to see if they are the same.
|
service items to see if they are the same.
|
||||||
"""
|
"""
|
||||||
self._uuid = unicode(uuid.uuid1())
|
self._uuid = unicode(uuid.uuid1())
|
||||||
|
self.validate_item()
|
||||||
|
|
||||||
def add_capability(self, capability):
|
def add_capability(self, capability):
|
||||||
"""
|
"""
|
||||||
@ -395,6 +399,7 @@ class ServiceItem(object):
|
|||||||
self.end_time = header.get(u'end_time', 0)
|
self.end_time = header.get(u'end_time', 0)
|
||||||
self.media_length = header.get(u'media_length', 0)
|
self.media_length = header.get(u'media_length', 0)
|
||||||
self.will_auto_start = header.get(u'will_auto_start', False)
|
self.will_auto_start = header.get(u'will_auto_start', False)
|
||||||
|
self.has_original_files = True
|
||||||
if u'background_audio' in header:
|
if u'background_audio' in header:
|
||||||
self.background_audio = []
|
self.background_audio = []
|
||||||
for filename in header[u'background_audio']:
|
for filename in header[u'background_audio']:
|
||||||
@ -405,16 +410,20 @@ class ServiceItem(object):
|
|||||||
for slide in serviceitem[u'serviceitem'][u'data']:
|
for slide in serviceitem[u'serviceitem'][u'data']:
|
||||||
self._raw_frames.append(slide)
|
self._raw_frames.append(slide)
|
||||||
elif self.service_item_type == ServiceItemType.Image:
|
elif self.service_item_type == ServiceItemType.Image:
|
||||||
|
settingsSection = serviceitem[u'serviceitem'][u'header'][u'name']
|
||||||
|
background = QtGui.QColor(Settings().value(settingsSection + u'/background color', u'#000000'))
|
||||||
if path:
|
if path:
|
||||||
|
self.has_original_files = False
|
||||||
for text_image in serviceitem[u'serviceitem'][u'data']:
|
for text_image in serviceitem[u'serviceitem'][u'data']:
|
||||||
filename = os.path.join(path, text_image)
|
filename = os.path.join(path, text_image)
|
||||||
self.add_from_image(filename, text_image)
|
self.add_from_image(filename, text_image, background)
|
||||||
else:
|
else:
|
||||||
for text_image in serviceitem[u'serviceitem'][u'data']:
|
for text_image in serviceitem[u'serviceitem'][u'data']:
|
||||||
self.add_from_image(text_image[u'path'], text_image[u'title'])
|
self.add_from_image(text_image[u'path'], text_image[u'title'], background)
|
||||||
elif self.service_item_type == ServiceItemType.Command:
|
elif self.service_item_type == ServiceItemType.Command:
|
||||||
for text_image in serviceitem[u'serviceitem'][u'data']:
|
for text_image in serviceitem[u'serviceitem'][u'data']:
|
||||||
if path:
|
if path:
|
||||||
|
self.has_original_files = False
|
||||||
self.add_from_command(path, text_image[u'title'], text_image[u'image'])
|
self.add_from_command(path, text_image[u'title'], text_image[u'image'])
|
||||||
else:
|
else:
|
||||||
self.add_from_command(text_image[u'path'], text_image[u'title'], text_image[u'image'])
|
self.add_from_command(text_image[u'path'], text_image[u'title'], text_image[u'image'])
|
||||||
@ -605,8 +614,25 @@ class ServiceItem(object):
|
|||||||
if self.get_frame_path(frame=frame) in invalid_paths:
|
if self.get_frame_path(frame=frame) in invalid_paths:
|
||||||
self.remove_frame(frame)
|
self.remove_frame(frame)
|
||||||
|
|
||||||
def validate(self):
|
def missing_frames(self):
|
||||||
"""
|
"""
|
||||||
Validates this service item
|
Returns if there are any frames in the service item
|
||||||
"""
|
"""
|
||||||
return bool(self._raw_frames)
|
return not bool(self._raw_frames)
|
||||||
|
|
||||||
|
def validate_item(self, suffix_list=None):
|
||||||
|
"""
|
||||||
|
Validates a service item to make sure it is valid
|
||||||
|
"""
|
||||||
|
self.is_valid = True
|
||||||
|
for frame in self._raw_frames:
|
||||||
|
if self.is_image() and not os.path.exists((frame[u'path'])):
|
||||||
|
self.is_valid = False
|
||||||
|
elif self.is_command():
|
||||||
|
file = os.path.join(frame[u'path'],frame[u'title'])
|
||||||
|
if not os.path.exists(file):
|
||||||
|
self.is_valid = False
|
||||||
|
if suffix_list and not self.is_text():
|
||||||
|
type = frame[u'title'].split(u'.')[-1]
|
||||||
|
if type.lower() not in suffix_list:
|
||||||
|
self.is_valid = False
|
||||||
|
@ -26,5 +26,9 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
"""
|
||||||
|
The :mod:`~openlp.core.theme` module contains all the themeing functions used by
|
||||||
|
OpenLP when displaying a song or a scripture.
|
||||||
|
"""
|
||||||
|
|
||||||
from openlp.core.theme.theme import Theme
|
from openlp.core.theme.theme import Theme
|
||||||
|
@ -29,9 +29,7 @@
|
|||||||
"""
|
"""
|
||||||
The :mod:`ui` module provides the core user interface for OpenLP
|
The :mod:`ui` module provides the core user interface for OpenLP
|
||||||
"""
|
"""
|
||||||
from PyQt4 import QtGui
|
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
|
||||||
|
|
||||||
class HideMode(object):
|
class HideMode(object):
|
||||||
"""
|
"""
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import translate, build_icon
|
from openlp.core.lib import translate
|
||||||
from openlp.core.lib.ui import create_button, create_button_box
|
from openlp.core.lib.ui import create_button, create_button_box
|
||||||
|
|
||||||
class Ui_ExceptionDialog(object):
|
class Ui_ExceptionDialog(object):
|
||||||
|
@ -29,19 +29,49 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import datetime
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import OpenLPToolbar, Receiver, translate, Settings
|
from openlp.core.lib import OpenLPToolbar, Receiver, translate, Settings
|
||||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||||
from openlp.core.ui.media import MediaState, MediaInfo, MediaType, \
|
from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players
|
||||||
get_media_players, set_media_players
|
|
||||||
from openlp.core.ui.media.mediaplayer import MediaPlayer
|
from openlp.core.ui.media.mediaplayer import MediaPlayer
|
||||||
from openlp.core.utils import AppLocation
|
from openlp.core.utils import AppLocation
|
||||||
from openlp.core.ui import DisplayControllerType
|
from openlp.core.ui import DisplayControllerType
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class MediaSlider(QtGui.QSlider):
|
||||||
|
"""
|
||||||
|
Allows the mouse events of a slider to be overridden and extra functionality added
|
||||||
|
"""
|
||||||
|
def __init__(self, direction, manager, controller, parent=None):
|
||||||
|
QtGui.QSlider.__init__(self, direction)
|
||||||
|
self.manager = manager
|
||||||
|
self.controller = controller
|
||||||
|
|
||||||
|
def mouseMoveEvent(self, event):
|
||||||
|
"""
|
||||||
|
Override event to allow hover time to be displayed.
|
||||||
|
"""
|
||||||
|
timevalue = QtGui.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), event.x(), self.width())
|
||||||
|
self.setToolTip(u'%s' % datetime.timedelta(seconds=int(timevalue/1000)))
|
||||||
|
QtGui.QSlider.mouseMoveEvent(self, event)
|
||||||
|
|
||||||
|
def mousePressEvent(self, event):
|
||||||
|
"""
|
||||||
|
Mouse Press event no new functionality
|
||||||
|
"""
|
||||||
|
QtGui.QSlider.mousePressEvent(self, event)
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, event):
|
||||||
|
"""
|
||||||
|
Set the slider position when the mouse is clicked and released on the slider.
|
||||||
|
"""
|
||||||
|
self.setValue(QtGui.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), event.x(), self.width()))
|
||||||
|
QtGui.QSlider.mouseReleaseEvent(self, event)
|
||||||
|
|
||||||
|
|
||||||
class MediaController(object):
|
class MediaController(object):
|
||||||
"""
|
"""
|
||||||
The implementation of the Media Controller. The Media Controller adds an own
|
The implementation of the Media Controller. The Media Controller adds an own
|
||||||
@ -69,8 +99,8 @@ class MediaController(object):
|
|||||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackPlay'), self.media_play_msg)
|
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackPlay'), self.media_play_msg)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackPause'), self.media_pause_msg)
|
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackPause'), self.media_pause_msg)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackStop'), self.media_stop_msg)
|
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackStop'), self.media_stop_msg)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'seekSlider'), self.media_seek)
|
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'seekSlider'), self.media_seek_msg)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'volumeSlider'), self.media_volume)
|
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'volumeSlider'), self.media_volume_msg)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_hide'), self.media_hide)
|
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_hide'), self.media_hide)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_blank'), self.media_blank)
|
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_blank'), self.media_blank)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_unblank'), self.media_unblank)
|
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_unblank'), self.media_unblank)
|
||||||
@ -241,9 +271,10 @@ class MediaController(object):
|
|||||||
icon=u':/slides/media_playback_stop.png',
|
icon=u':/slides/media_playback_stop.png',
|
||||||
tooltip=translate('OpenLP.SlideController', 'Stop playing media.'), triggers=controller.sendToPlugins)
|
tooltip=translate('OpenLP.SlideController', 'Stop playing media.'), triggers=controller.sendToPlugins)
|
||||||
# Build the seekSlider.
|
# Build the seekSlider.
|
||||||
controller.seekSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
|
controller.seekSlider = MediaSlider(QtCore.Qt.Horizontal, self, controller)
|
||||||
controller.seekSlider.setMaximum(1000)
|
controller.seekSlider.setMaximum(1000)
|
||||||
controller.seekSlider.setTracking(False)
|
controller.seekSlider.setTracking(True)
|
||||||
|
controller.seekSlider.setMouseTracking(True)
|
||||||
controller.seekSlider.setToolTip(translate('OpenLP.SlideController', 'Video position.'))
|
controller.seekSlider.setToolTip(translate('OpenLP.SlideController', 'Video position.'))
|
||||||
controller.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
|
controller.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
|
||||||
controller.seekSlider.setObjectName(u'seekSlider')
|
controller.seekSlider.setObjectName(u'seekSlider')
|
||||||
@ -344,12 +375,8 @@ class MediaController(object):
|
|||||||
# stop running videos
|
# stop running videos
|
||||||
self.media_reset(controller)
|
self.media_reset(controller)
|
||||||
controller.media_info = MediaInfo()
|
controller.media_info = MediaInfo()
|
||||||
if videoBehindText:
|
controller.media_info.volume = controller.volumeSlider.value()
|
||||||
controller.media_info.volume = 0
|
controller.media_info.is_background = videoBehindText
|
||||||
controller.media_info.is_background = True
|
|
||||||
else:
|
|
||||||
controller.media_info.volume = controller.volumeSlider.value()
|
|
||||||
controller.media_info.is_background = False
|
|
||||||
controller.media_info.file_info = QtCore.QFileInfo(serviceItem.get_frame_path())
|
controller.media_info.file_info = QtCore.QFileInfo(serviceItem.get_frame_path())
|
||||||
display = self._define_display(controller)
|
display = self._define_display(controller)
|
||||||
if controller.isLive:
|
if controller.isLive:
|
||||||
@ -361,7 +388,7 @@ class MediaController(object):
|
|||||||
controller.media_info.start_time = 0
|
controller.media_info.start_time = 0
|
||||||
controller.media_info.end_time = 0
|
controller.media_info.end_time = 0
|
||||||
else:
|
else:
|
||||||
controller.media_info.start_time = display.serviceItem.start_time
|
controller.media_info.start_time = serviceItem.start_time
|
||||||
controller.media_info.end_time = serviceItem.end_time
|
controller.media_info.end_time = serviceItem.end_time
|
||||||
elif controller.previewDisplay:
|
elif controller.previewDisplay:
|
||||||
isValid = self._check_file_type(controller, display, serviceItem)
|
isValid = self._check_file_type(controller, display, serviceItem)
|
||||||
@ -483,9 +510,17 @@ class MediaController(object):
|
|||||||
The controller to be played
|
The controller to be played
|
||||||
"""
|
"""
|
||||||
log.debug(u'media_play')
|
log.debug(u'media_play')
|
||||||
|
controller.seekSlider.blockSignals(True)
|
||||||
|
controller.volumeSlider.blockSignals(True)
|
||||||
display = self._define_display(controller)
|
display = self._define_display(controller)
|
||||||
if not self.currentMediaPlayer[controller.controllerType].play(display):
|
if not self.currentMediaPlayer[controller.controllerType].play(display):
|
||||||
|
controller.seekSlider.blockSignals(False)
|
||||||
|
controller.volumeSlider.blockSignals(False)
|
||||||
return False
|
return False
|
||||||
|
if controller.media_info.is_background:
|
||||||
|
self.media_volume(controller, 0)
|
||||||
|
else:
|
||||||
|
self.media_volume(controller, controller.media_info.volume)
|
||||||
if status:
|
if status:
|
||||||
display.frame.evaluateJavaScript(u'show_blank("desktop");')
|
display.frame.evaluateJavaScript(u'show_blank("desktop");')
|
||||||
self.currentMediaPlayer[controller.controllerType].set_visible(display, True)
|
self.currentMediaPlayer[controller.controllerType].set_visible(display, True)
|
||||||
@ -503,6 +538,8 @@ class MediaController(object):
|
|||||||
# Start Timer for ui updates
|
# Start Timer for ui updates
|
||||||
if not self.timer.isActive():
|
if not self.timer.isActive():
|
||||||
self.timer.start()
|
self.timer.start()
|
||||||
|
controller.seekSlider.blockSignals(False)
|
||||||
|
controller.volumeSlider.blockSignals(False)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def media_pause_msg(self, msg):
|
def media_pause_msg(self, msg):
|
||||||
@ -557,7 +594,7 @@ class MediaController(object):
|
|||||||
controller.mediabar.actions[u'playbackStop'].setVisible(False)
|
controller.mediabar.actions[u'playbackStop'].setVisible(False)
|
||||||
controller.mediabar.actions[u'playbackPause'].setVisible(False)
|
controller.mediabar.actions[u'playbackPause'].setVisible(False)
|
||||||
|
|
||||||
def media_volume(self, msg):
|
def media_volume_msg(self, msg):
|
||||||
"""
|
"""
|
||||||
Changes the volume of a running video
|
Changes the volume of a running video
|
||||||
|
|
||||||
@ -566,11 +603,21 @@ class MediaController(object):
|
|||||||
"""
|
"""
|
||||||
controller = msg[0]
|
controller = msg[0]
|
||||||
vol = msg[1][0]
|
vol = msg[1][0]
|
||||||
log.debug(u'media_volume %d' % vol)
|
self.media_volume(controller, vol)
|
||||||
display = self._define_display(controller)
|
|
||||||
self.currentMediaPlayer[controller.controllerType].volume(display, vol)
|
|
||||||
|
|
||||||
def media_seek(self, msg):
|
def media_volume(self, controller, volume):
|
||||||
|
"""
|
||||||
|
Changes the volume of a running video
|
||||||
|
|
||||||
|
``msg``
|
||||||
|
First element is the controller which should be used
|
||||||
|
"""
|
||||||
|
log.debug(u'media_volume %d' % volume)
|
||||||
|
display = self._define_display(controller)
|
||||||
|
self.currentMediaPlayer[controller.controllerType].volume(display, volume)
|
||||||
|
controller.volumeSlider.setValue(volume)
|
||||||
|
|
||||||
|
def media_seek_msg(self, msg):
|
||||||
"""
|
"""
|
||||||
Responds to the request to change the seek Slider of a loaded video
|
Responds to the request to change the seek Slider of a loaded video
|
||||||
|
|
||||||
@ -581,6 +628,17 @@ class MediaController(object):
|
|||||||
log.debug(u'media_seek')
|
log.debug(u'media_seek')
|
||||||
controller = msg[0]
|
controller = msg[0]
|
||||||
seekVal = msg[1][0]
|
seekVal = msg[1][0]
|
||||||
|
self.media_seek(controller, seekVal)
|
||||||
|
|
||||||
|
def media_seek(self, controller, seekVal):
|
||||||
|
"""
|
||||||
|
Responds to the request to change the seek Slider of a loaded video
|
||||||
|
|
||||||
|
``msg``
|
||||||
|
First element is the controller which should be used
|
||||||
|
Second element is a list with the seek Value as first element
|
||||||
|
"""
|
||||||
|
log.debug(u'media_seek')
|
||||||
display = self._define_display(controller)
|
display = self._define_display(controller)
|
||||||
self.currentMediaPlayer[controller.controllerType].seek(display, seekVal)
|
self.currentMediaPlayer[controller.controllerType].seek(display, seekVal)
|
||||||
|
|
||||||
@ -610,7 +668,8 @@ class MediaController(object):
|
|||||||
return
|
return
|
||||||
controller = self.mainWindow.liveController
|
controller = self.mainWindow.liveController
|
||||||
display = self._define_display(controller)
|
display = self._define_display(controller)
|
||||||
if self.currentMediaPlayer[controller.controllerType].state == MediaState.Playing:
|
if controller.controllerType in self.currentMediaPlayer and \
|
||||||
|
self.currentMediaPlayer[controller.controllerType].state == MediaState.Playing:
|
||||||
self.currentMediaPlayer[controller.controllerType].pause(display)
|
self.currentMediaPlayer[controller.controllerType].pause(display)
|
||||||
self.currentMediaPlayer[controller.controllerType].set_visible(display, False)
|
self.currentMediaPlayer[controller.controllerType].set_visible(display, False)
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ import logging
|
|||||||
import mimetypes
|
import mimetypes
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtGui
|
||||||
from PyQt4.phonon import Phonon
|
from PyQt4.phonon import Phonon
|
||||||
|
|
||||||
from openlp.core.lib import Receiver, translate, Settings
|
from openlp.core.lib import Receiver, translate, Settings
|
||||||
@ -215,8 +215,9 @@ class PhononPlayer(MediaPlayer):
|
|||||||
self.stop(display)
|
self.stop(display)
|
||||||
self.set_visible(display, False)
|
self.set_visible(display, False)
|
||||||
if not controller.seekSlider.isSliderDown():
|
if not controller.seekSlider.isSliderDown():
|
||||||
controller.seekSlider.setSliderPosition(
|
controller.seekSlider.blockSignals(True)
|
||||||
display.mediaObject.currentTime())
|
controller.seekSlider.setSliderPosition(display.mediaObject.currentTime())
|
||||||
|
controller.seekSlider.blockSignals(False)
|
||||||
|
|
||||||
def get_media_display_css(self):
|
def get_media_display_css(self):
|
||||||
"""
|
"""
|
||||||
|
4
openlp/core/ui/media/vendor/__init__.py
vendored
4
openlp/core/ui/media/vendor/__init__.py
vendored
@ -26,3 +26,7 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
"""
|
||||||
|
The :mod:`~openlp.core.ui.media.vendor` module contains any scripts or libraries
|
||||||
|
from 3rd party vendors which are required to make certain media modules work.
|
||||||
|
"""
|
||||||
|
@ -33,7 +33,7 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
from openlp.core.lib import Receiver, translate, Settings
|
from openlp.core.lib import Receiver, translate, Settings
|
||||||
from openlp.core.ui.media import MediaState
|
from openlp.core.ui.media import MediaState
|
||||||
@ -109,6 +109,7 @@ class VlcPlayer(MediaPlayer):
|
|||||||
|
|
||||||
def setup(self, display):
|
def setup(self, display):
|
||||||
display.vlcWidget = QtGui.QFrame(display)
|
display.vlcWidget = QtGui.QFrame(display)
|
||||||
|
display.vlcWidget.setFrameStyle(QtGui.QFrame.NoFrame)
|
||||||
# creating a basic vlc instance
|
# creating a basic vlc instance
|
||||||
command_line_options = u'--no-video-title-show'
|
command_line_options = u'--no-video-title-show'
|
||||||
if not display.hasAudio:
|
if not display.hasAudio:
|
||||||
@ -188,6 +189,7 @@ class VlcPlayer(MediaPlayer):
|
|||||||
display.vlcMediaPlayer.play()
|
display.vlcMediaPlayer.play()
|
||||||
if not self.media_state_wait(display, vlc.State.Playing):
|
if not self.media_state_wait(display, vlc.State.Playing):
|
||||||
return False
|
return False
|
||||||
|
self.volume(display, controller.media_info.volume)
|
||||||
if start_time > 0:
|
if start_time > 0:
|
||||||
self.seek(display, controller.media_info.start_time * 1000)
|
self.seek(display, controller.media_info.start_time * 1000)
|
||||||
controller.media_info.length = int(display.vlcMediaPlayer.get_media().get_duration() / 1000)
|
controller.media_info.length = int(display.vlcMediaPlayer.get_media().get_duration() / 1000)
|
||||||
@ -234,7 +236,9 @@ class VlcPlayer(MediaPlayer):
|
|||||||
self.stop(display)
|
self.stop(display)
|
||||||
self.set_visible(display, False)
|
self.set_visible(display, False)
|
||||||
if not controller.seekSlider.isSliderDown():
|
if not controller.seekSlider.isSliderDown():
|
||||||
|
controller.seekSlider.blockSignals(True)
|
||||||
controller.seekSlider.setSliderPosition(display.vlcMediaPlayer.get_time())
|
controller.seekSlider.setSliderPosition(display.vlcMediaPlayer.get_time())
|
||||||
|
controller.seekSlider.blockSignals(False)
|
||||||
|
|
||||||
def get_info(self):
|
def get_info(self):
|
||||||
return(translate('Media.player', 'VLC is an external player which '
|
return(translate('Media.player', 'VLC is an external player which '
|
||||||
|
@ -423,7 +423,9 @@ class WebkitPlayer(MediaPlayer):
|
|||||||
controller.media_info.length = length
|
controller.media_info.length = length
|
||||||
controller.seekSlider.setMaximum(length)
|
controller.seekSlider.setMaximum(length)
|
||||||
if not controller.seekSlider.isSliderDown():
|
if not controller.seekSlider.isSliderDown():
|
||||||
|
controller.seekSlider.blockSignals(True)
|
||||||
controller.seekSlider.setSliderPosition(currentTime)
|
controller.seekSlider.setSliderPosition(currentTime)
|
||||||
|
controller.seekSlider.blockSignals(False)
|
||||||
|
|
||||||
def get_info(self):
|
def get_info(self):
|
||||||
return(translate('Media.player', 'Webkit is a media player which runs '
|
return(translate('Media.player', 'Webkit is a media player which runs '
|
||||||
|
@ -69,7 +69,7 @@ class ScreenList(object):
|
|||||||
screen_list.screen_list = []
|
screen_list.screen_list = []
|
||||||
screen_list.display_count = 0
|
screen_list.display_count = 0
|
||||||
screen_list.screen_count_changed()
|
screen_list.screen_count_changed()
|
||||||
screen_list._load_screen_settings()
|
screen_list.load_screen_settings()
|
||||||
QtCore.QObject.connect(desktop, QtCore.SIGNAL(u'resized(int)'), screen_list.screen_resolution_changed)
|
QtCore.QObject.connect(desktop, QtCore.SIGNAL(u'resized(int)'), screen_list.screen_resolution_changed)
|
||||||
QtCore.QObject.connect(desktop, QtCore.SIGNAL(u'screenCountChanged(int)'), screen_list.screen_count_changed)
|
QtCore.QObject.connect(desktop, QtCore.SIGNAL(u'screenCountChanged(int)'), screen_list.screen_count_changed)
|
||||||
return screen_list
|
return screen_list
|
||||||
@ -237,7 +237,7 @@ class ScreenList(object):
|
|||||||
y >= size.y() and y <= (size.y() + size.height()):
|
y >= size.y() and y <= (size.y() + size.height()):
|
||||||
return screen[u'number']
|
return screen[u'number']
|
||||||
|
|
||||||
def _load_screen_settings(self):
|
def load_screen_settings(self):
|
||||||
"""
|
"""
|
||||||
Loads the screen size and the monitor number from the settings.
|
Loads the screen size and the monitor number from the settings.
|
||||||
"""
|
"""
|
||||||
|
@ -114,6 +114,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
# is a new service and has not been saved
|
# is a new service and has not been saved
|
||||||
self._modified = False
|
self._modified = False
|
||||||
self._fileName = u''
|
self._fileName = u''
|
||||||
|
self.service_has_all_original_files = True
|
||||||
self.serviceNoteForm = ServiceNoteForm(self.mainwindow)
|
self.serviceNoteForm = ServiceNoteForm(self.mainwindow)
|
||||||
self.serviceItemEditForm = ServiceItemEditForm(self.mainwindow)
|
self.serviceItemEditForm = ServiceItemEditForm(self.mainwindow)
|
||||||
self.startTimeForm = StartTimeForm(self.mainwindow)
|
self.startTimeForm = StartTimeForm(self.mainwindow)
|
||||||
@ -458,7 +459,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
for item in list(self.serviceItems):
|
for item in list(self.serviceItems):
|
||||||
self.mainwindow.incrementProgressBar()
|
self.mainwindow.incrementProgressBar()
|
||||||
item[u'service_item'].remove_invalid_frames(missing_list)
|
item[u'service_item'].remove_invalid_frames(missing_list)
|
||||||
if not item[u'service_item'].validate():
|
if item[u'service_item'].missing_frames():
|
||||||
self.serviceItems.remove(item)
|
self.serviceItems.remove(item)
|
||||||
else:
|
else:
|
||||||
service_item = item[u'service_item'].get_service_repr(self._saveLite)
|
service_item = item[u'service_item'].get_service_repr(self._saveLite)
|
||||||
@ -620,7 +621,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
path = os.path.join(directory, default_filename)
|
path = os.path.join(directory, default_filename)
|
||||||
# SaveAs from osz to oszl is not valid as the files will be deleted
|
# SaveAs from osz to oszl is not valid as the files will be deleted
|
||||||
# on exit which is not sensible or usable in the long term.
|
# on exit which is not sensible or usable in the long term.
|
||||||
if self._fileName.endswith(u'oszl') or not self._fileName:
|
if self._fileName.endswith(u'oszl') or self.service_has_all_original_files:
|
||||||
fileName = QtGui.QFileDialog.getSaveFileName(self.mainwindow, UiStrings().SaveService, path,
|
fileName = QtGui.QFileDialog.getSaveFileName(self.mainwindow, UiStrings().SaveService, path,
|
||||||
translate('OpenLP.ServiceManager',
|
translate('OpenLP.ServiceManager',
|
||||||
'OpenLP Service Files (*.osz);; OpenLP Service Files - lite (*.oszl)'))
|
'OpenLP Service Files (*.osz);; OpenLP Service Files - lite (*.oszl)'))
|
||||||
@ -693,7 +694,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
serviceItem.set_from_service(item)
|
serviceItem.set_from_service(item)
|
||||||
else:
|
else:
|
||||||
serviceItem.set_from_service(item, self.servicePath)
|
serviceItem.set_from_service(item, self.servicePath)
|
||||||
self.validateItem(serviceItem)
|
serviceItem.validate_item(self.suffixes)
|
||||||
self.load_item_uuid = 0
|
self.load_item_uuid = 0
|
||||||
if serviceItem.is_capable(ItemCapabilities.OnLoadUpdate):
|
if serviceItem.is_capable(ItemCapabilities.OnLoadUpdate):
|
||||||
Receiver.send_message(u'%s_service_load' % serviceItem.name.lower(), serviceItem)
|
Receiver.send_message(u'%s_service_load' % serviceItem.name.lower(), serviceItem)
|
||||||
@ -1032,9 +1033,12 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
"""
|
"""
|
||||||
# Correct order of items in array
|
# Correct order of items in array
|
||||||
count = 1
|
count = 1
|
||||||
|
self.service_has_all_original_files = True
|
||||||
for item in self.serviceItems:
|
for item in self.serviceItems:
|
||||||
item[u'order'] = count
|
item[u'order'] = count
|
||||||
count += 1
|
count += 1
|
||||||
|
if not item[u'service_item'].has_original_files:
|
||||||
|
self.service_has_all_original_files = False
|
||||||
# Repaint the screen
|
# Repaint the screen
|
||||||
self.serviceManagerList.clear()
|
self.serviceManagerList.clear()
|
||||||
for itemcount, item in enumerate(self.serviceItems):
|
for itemcount, item in enumerate(self.serviceItems):
|
||||||
@ -1093,18 +1097,6 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.serviceManagerList.setCurrentItem(treewidgetitem)
|
self.serviceManagerList.setCurrentItem(treewidgetitem)
|
||||||
treewidgetitem.setExpanded(item[u'expanded'])
|
treewidgetitem.setExpanded(item[u'expanded'])
|
||||||
|
|
||||||
def validateItem(self, serviceItem):
|
|
||||||
"""
|
|
||||||
Validates the service item and if the suffix matches an accepted
|
|
||||||
one it allows the item to be displayed.
|
|
||||||
"""
|
|
||||||
#@todo check file items exist
|
|
||||||
if serviceItem.is_command():
|
|
||||||
type = serviceItem._raw_frames[0][u'title'].split(u'.')[-1]
|
|
||||||
if type.lower() not in self.suffixes:
|
|
||||||
serviceItem.is_valid = False
|
|
||||||
#@todo check file items exist
|
|
||||||
|
|
||||||
def cleanUp(self):
|
def cleanUp(self):
|
||||||
"""
|
"""
|
||||||
Empties the servicePath of temporary files on system exit.
|
Empties the servicePath of temporary files on system exit.
|
||||||
@ -1144,7 +1136,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
log.debug(u'regenerateServiceItems')
|
log.debug(u'regenerateServiceItems')
|
||||||
# force reset of renderer as theme data has changed
|
# force reset of renderer as theme data has changed
|
||||||
self.mainwindow.renderer.themedata = None
|
self.service_has_all_original_files = True
|
||||||
if self.serviceItems:
|
if self.serviceItems:
|
||||||
for item in self.serviceItems:
|
for item in self.serviceItems:
|
||||||
item[u'selected'] = False
|
item[u'selected'] = False
|
||||||
|
@ -31,7 +31,7 @@ The :mod:`settingsform` provides a user interface for the OpenLP settings
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
from openlp.core.lib import Receiver, build_icon, PluginStatus
|
from openlp.core.lib import Receiver, build_icon, PluginStatus
|
||||||
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
|
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
|
||||||
@ -141,4 +141,4 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
|
|||||||
"""
|
"""
|
||||||
if self.resetSuffixes:
|
if self.resetSuffixes:
|
||||||
self.mainWindow.serviceManagerContents.resetSupportedSuffixes()
|
self.mainWindow.serviceManagerContents.resetSupportedSuffixes()
|
||||||
self.resetSuffixes = False
|
self.resetSuffixes = False
|
||||||
|
@ -933,8 +933,7 @@ class SlideController(DisplayController):
|
|||||||
else:
|
else:
|
||||||
if not self.serviceItem.is_command():
|
if not self.serviceItem.is_command():
|
||||||
Receiver.send_message(u'live_display_show')
|
Receiver.send_message(u'live_display_show')
|
||||||
Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(),
|
Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
|
||||||
[self.serviceItem, self.isLive])
|
|
||||||
else:
|
else:
|
||||||
if hide_mode:
|
if hide_mode:
|
||||||
Receiver.send_message(u'live_display_hide', hide_mode)
|
Receiver.send_message(u'live_display_hide', hide_mode)
|
||||||
@ -949,13 +948,11 @@ class SlideController(DisplayController):
|
|||||||
if self.serviceItem is not None:
|
if self.serviceItem is not None:
|
||||||
if hide:
|
if hide:
|
||||||
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
Receiver.send_message(u'%s_hide' % self.serviceItem.name.lower(),
|
Receiver.send_message(u'%s_hide' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
|
||||||
[self.serviceItem, self.isLive])
|
|
||||||
else:
|
else:
|
||||||
if not self.serviceItem.is_command():
|
if not self.serviceItem.is_command():
|
||||||
Receiver.send_message(u'live_display_show')
|
Receiver.send_message(u'live_display_show')
|
||||||
Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(),
|
Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
|
||||||
[self.serviceItem, self.isLive])
|
|
||||||
else:
|
else:
|
||||||
if hide:
|
if hide:
|
||||||
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
@ -995,6 +992,7 @@ class SlideController(DisplayController):
|
|||||||
self.selectedRow = row
|
self.selectedRow = row
|
||||||
self.__checkUpdateSelectedSlide(row)
|
self.__checkUpdateSelectedSlide(row)
|
||||||
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row)
|
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row)
|
||||||
|
self.display.setFocus()
|
||||||
|
|
||||||
def onSlideChange(self, row):
|
def onSlideChange(self, row):
|
||||||
"""
|
"""
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
"""
|
"""
|
||||||
The :mod:`openlp.core.utils` module provides the utility libraries for OpenLP.
|
The :mod:`openlp.core.utils` module provides the utility libraries for OpenLP.
|
||||||
"""
|
"""
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
import logging
|
import logging
|
||||||
import locale
|
import locale
|
||||||
@ -277,20 +277,31 @@ def check_latest_version(current_version):
|
|||||||
|
|
||||||
``current_version``
|
``current_version``
|
||||||
The current version of OpenLP.
|
The current version of OpenLP.
|
||||||
|
|
||||||
|
**Rules around versions and version files:**
|
||||||
|
|
||||||
|
* If a version number has a build (i.e. -bzr1234), then it is a nightly.
|
||||||
|
* If a version number's minor version is an odd number, it is a development release.
|
||||||
|
* If a version number's minor version is an even number, it is a stable release.
|
||||||
"""
|
"""
|
||||||
version_string = current_version[u'full']
|
version_string = current_version[u'full']
|
||||||
# set to prod in the distribution config file.
|
# set to prod in the distribution config file.
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
settings.beginGroup(u'general')
|
settings.beginGroup(u'general')
|
||||||
last_test = settings.value(u'last version test', datetime.now().date())
|
# This defaults to yesterday in order to force the update check to run when you've never run it before.
|
||||||
|
last_test = settings.value(u'last version test', datetime.now().date() - timedelta(days=1))
|
||||||
this_test = datetime.now().date()
|
this_test = datetime.now().date()
|
||||||
settings.setValue(u'last version test', this_test)
|
settings.setValue(u'last version test', this_test)
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
if last_test != this_test:
|
if last_test != this_test:
|
||||||
if current_version[u'build']:
|
if current_version[u'build']:
|
||||||
req = urllib2.Request(u'http://www.openlp.org/files/dev_version.txt')
|
req = urllib2.Request(u'http://www.openlp.org/files/nightly_version.txt')
|
||||||
else:
|
else:
|
||||||
req = urllib2.Request(u'http://www.openlp.org/files/version.txt')
|
version_parts = current_version[u'version'].split(u'.')
|
||||||
|
if int(version_parts[1]) % 2 != 0:
|
||||||
|
req = urllib2.Request(u'http://www.openlp.org/files/dev_version.txt')
|
||||||
|
else:
|
||||||
|
req = urllib2.Request(u'http://www.openlp.org/files/version.txt')
|
||||||
req.add_header(u'User-Agent', u'OpenLP/%s' % current_version[u'full'])
|
req.add_header(u'User-Agent', u'OpenLP/%s' % current_version[u'full'])
|
||||||
remote_version = None
|
remote_version = None
|
||||||
try:
|
try:
|
||||||
|
@ -26,5 +26,31 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
"""
|
||||||
|
Forms in OpenLP are made up of two classes. One class holds all the graphical
|
||||||
|
elements, like buttons and lists, and the other class holds all the functional
|
||||||
|
code, like slots and loading and saving.
|
||||||
|
|
||||||
|
The first class, commonly known as the **Dialog** class, is typically named
|
||||||
|
``Ui_<name>Dialog``. It is a slightly modified version of the class that the
|
||||||
|
``pyuic4`` command produces from Qt4's .ui file. Typical modifications will be
|
||||||
|
converting most strings from "" to u'' and using OpenLP's ``translate()``
|
||||||
|
function for translating strings.
|
||||||
|
|
||||||
|
The second class, commonly known as the **Form** class, is typically named
|
||||||
|
``<name>Form``. This class is the one which is instantiated and used. It uses
|
||||||
|
dual inheritance to inherit from (usually) QtGui.QDialog and the Ui class
|
||||||
|
mentioned above, like so::
|
||||||
|
|
||||||
|
class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QtGui.QDialog.__init__(self, parent)
|
||||||
|
self.setupUi(self)
|
||||||
|
|
||||||
|
This allows OpenLP to use ``self.object`` for all the GUI elements while keeping
|
||||||
|
them separate from the functionality, so that it is easier to recreate the GUI
|
||||||
|
from the .ui files later if necessary.
|
||||||
|
"""
|
||||||
|
|
||||||
from alertform import AlertForm
|
from alertform import AlertForm
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
"""
|
||||||
|
The :mod:`~openlp.plugins.alerts.lib.alertsmanager` module contains the part of
|
||||||
|
the plugin which manages storing and displaying of alerts.
|
||||||
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate, Settings
|
from openlp.core.lib import Plugin, StringContent, build_icon, translate, Settings
|
||||||
from openlp.core.lib.ui import create_action, UiStrings
|
from openlp.core.lib.ui import create_action, UiStrings
|
||||||
|
@ -34,7 +34,7 @@ import logging
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from openlp.core.lib import translate, Settings
|
from openlp.core.lib import translate, Settings
|
||||||
from openlp.plugins.bibles.lib.db import BiblesResourcesDB
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -30,8 +30,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
|
||||||
|
|
||||||
from openlp.core.lib import Receiver, SettingsManager, translate, Settings
|
from openlp.core.lib import Receiver, SettingsManager, translate, Settings
|
||||||
from openlp.core.utils import AppLocation, delete_file
|
from openlp.core.utils import AppLocation, delete_file
|
||||||
from openlp.plugins.bibles.lib import parse_reference, get_reference_separator, LanguageSelection
|
from openlp.plugins.bibles.lib import parse_reference, get_reference_separator, LanguageSelection
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
"""
|
||||||
|
The :mod:`~openlp.plugins.custom.customplugin` module contains the Plugin class
|
||||||
|
for the Custom Slides plugin.
|
||||||
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
"""
|
||||||
|
The :mod:`~openlp.plugins.custom.lib.customtab` module contains the settings tab
|
||||||
|
for the Custom Slides plugin, which is inserted into the configuration dialog.
|
||||||
|
"""
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
@ -66,6 +70,9 @@ class CustomTab(SettingsTab):
|
|||||||
'Import missing custom slides from service files'))
|
'Import missing custom slides from service files'))
|
||||||
|
|
||||||
def onDisplayFooterCheckBoxChanged(self, check_state):
|
def onDisplayFooterCheckBoxChanged(self, check_state):
|
||||||
|
"""
|
||||||
|
Toggle the setting for displaying the footer.
|
||||||
|
"""
|
||||||
self.displayFooter = False
|
self.displayFooter = False
|
||||||
# we have a set value convert to True/False
|
# we have a set value convert to True/False
|
||||||
if check_state == QtCore.Qt.Checked:
|
if check_state == QtCore.Qt.Checked:
|
||||||
|
@ -50,6 +50,7 @@ from lxml import etree, objectify
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
#TODO: These classes need to be refactored into a single class.
|
||||||
class CustomXMLBuilder(object):
|
class CustomXMLBuilder(object):
|
||||||
"""
|
"""
|
||||||
This class builds the XML used to describe songs.
|
This class builds the XML used to describe songs.
|
||||||
@ -84,11 +85,11 @@ class CustomXMLBuilder(object):
|
|||||||
self.lyrics.setAttribute(u'language', u'en')
|
self.lyrics.setAttribute(u'language', u'en')
|
||||||
self.song.appendChild(self.lyrics)
|
self.song.appendChild(self.lyrics)
|
||||||
|
|
||||||
def add_verse_to_lyrics(self, type, number, content):
|
def add_verse_to_lyrics(self, verse_type, number, content):
|
||||||
"""
|
"""
|
||||||
Add a verse to the ``<lyrics>`` tag.
|
Add a verse to the ``<lyrics>`` tag.
|
||||||
|
|
||||||
``type``
|
``verse_type``
|
||||||
A string denoting the type of verse. Possible values are "Chorus",
|
A string denoting the type of verse. Possible values are "Chorus",
|
||||||
"Verse", "Bridge", and "Custom".
|
"Verse", "Bridge", and "Custom".
|
||||||
|
|
||||||
@ -99,7 +100,7 @@ class CustomXMLBuilder(object):
|
|||||||
The actual text of the verse to be stored.
|
The actual text of the verse to be stored.
|
||||||
"""
|
"""
|
||||||
verse = self.custom_xml.createElement(u'verse')
|
verse = self.custom_xml.createElement(u'verse')
|
||||||
verse.setAttribute(u'type', type)
|
verse.setAttribute(u'type', verse_type)
|
||||||
verse.setAttribute(u'label', number)
|
verse.setAttribute(u'label', number)
|
||||||
self.lyrics.appendChild(verse)
|
self.lyrics.appendChild(verse)
|
||||||
# add data as a CDATA section to protect the XML from special chars
|
# add data as a CDATA section to protect the XML from special chars
|
||||||
|
@ -33,11 +33,11 @@ import os
|
|||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, SettingsManager, translate, \
|
from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, SettingsManager, translate, \
|
||||||
check_item_selected, Receiver, MediaType, ServiceItem, build_html, ServiceItemContext, Settings
|
check_item_selected, Receiver, MediaType, ServiceItem, ServiceItemContext, Settings, check_directory_exists
|
||||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box, create_horizontal_adjusting_combo_box
|
from openlp.core.lib.ui import UiStrings, critical_error_message_box, create_horizontal_adjusting_combo_box
|
||||||
from openlp.core.ui import DisplayController, Display, DisplayControllerType
|
from openlp.core.ui import DisplayController, Display, DisplayControllerType
|
||||||
from openlp.core.ui.media import get_media_players, set_media_players
|
from openlp.core.ui.media import get_media_players, set_media_players
|
||||||
from openlp.core.utils import locale_compare
|
from openlp.core.utils import AppLocation, locale_compare
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -130,8 +130,7 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
"""
|
"""
|
||||||
Called to reset the Live background with the media selected,
|
Called to reset the Live background with the media selected,
|
||||||
"""
|
"""
|
||||||
self.plugin.liveController.mediaController.media_reset(
|
self.plugin.liveController.mediaController.media_reset(self.plugin.liveController)
|
||||||
self.plugin.liveController)
|
|
||||||
self.resetAction.setVisible(False)
|
self.resetAction.setVisible(False)
|
||||||
|
|
||||||
def videobackgroundReplaced(self):
|
def videobackgroundReplaced(self):
|
||||||
@ -145,8 +144,7 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
Called to replace Live background with the media selected.
|
Called to replace Live background with the media selected.
|
||||||
"""
|
"""
|
||||||
if check_item_selected(self.listView,
|
if check_item_selected(self.listView,
|
||||||
translate('MediaPlugin.MediaItem',
|
translate('MediaPlugin.MediaItem', 'You must select a media file to replace the background with.')):
|
||||||
'You must select a media file to replace the background with.')):
|
|
||||||
item = self.listView.currentItem()
|
item = self.listView.currentItem()
|
||||||
filename = item.data(QtCore.Qt.UserRole)
|
filename = item.data(QtCore.Qt.UserRole)
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
@ -166,8 +164,8 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
translate('MediaPlugin.MediaItem',
|
translate('MediaPlugin.MediaItem',
|
||||||
'There was a problem replacing your background, the media file "%s" no longer exists.') % filename)
|
'There was a problem replacing your background, the media file "%s" no longer exists.') % filename)
|
||||||
|
|
||||||
def generateSlideData(self, service_item, item=None, xmlVersion=False,
|
def generateSlideData(self, service_item, item=None, xmlVersion=False, remote=False,
|
||||||
remote=False, context=ServiceItemContext.Live):
|
context=ServiceItemContext.Live):
|
||||||
if item is None:
|
if item is None:
|
||||||
item = self.listView.currentItem()
|
item = self.listView.currentItem()
|
||||||
if item is None:
|
if item is None:
|
||||||
@ -201,6 +199,8 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
def initialise(self):
|
def initialise(self):
|
||||||
self.listView.clear()
|
self.listView.clear()
|
||||||
self.listView.setIconSize(QtCore.QSize(88, 50))
|
self.listView.setIconSize(QtCore.QSize(88, 50))
|
||||||
|
self.servicePath = os.path.join(AppLocation.get_section_data_path(self.settingsSection), u'thumbnails')
|
||||||
|
check_directory_exists(self.servicePath)
|
||||||
self.loadList(SettingsManager.load_list(self.settingsSection, u'media'))
|
self.loadList(SettingsManager.load_list(self.settingsSection, u'media'))
|
||||||
self.populateDisplayTypes()
|
self.populateDisplayTypes()
|
||||||
|
|
||||||
@ -247,14 +247,13 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
"""
|
"""
|
||||||
Remove a media item from the list.
|
Remove a media item from the list.
|
||||||
"""
|
"""
|
||||||
if check_item_selected(self.listView, translate('MediaPlugin.MediaItem',
|
if check_item_selected(self.listView,
|
||||||
'You must select a media file to delete.')):
|
translate('MediaPlugin.MediaItem', 'You must select a media file to delete.')):
|
||||||
row_list = [item.row() for item in self.listView.selectedIndexes()]
|
row_list = [item.row() for item in self.listView.selectedIndexes()]
|
||||||
row_list.sort(reverse=True)
|
row_list.sort(reverse=True)
|
||||||
for row in row_list:
|
for row in row_list:
|
||||||
self.listView.takeItem(row)
|
self.listView.takeItem(row)
|
||||||
SettingsManager.set_list(self.settingsSection,
|
SettingsManager.set_list(self.settingsSection, u'media', self.getFileList())
|
||||||
u'media', self.getFileList())
|
|
||||||
|
|
||||||
def loadList(self, media):
|
def loadList(self, media):
|
||||||
# Sort the media by its filename considering language specific
|
# Sort the media by its filename considering language specific
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class PresentationPlugin(Plugin):
|
|||||||
if self.controllers[controller].enabled():
|
if self.controllers[controller].enabled():
|
||||||
try:
|
try:
|
||||||
self.controllers[controller].start_process()
|
self.controllers[controller].start_process()
|
||||||
except:
|
except Exception:
|
||||||
log.warn(u'Failed to start controller process')
|
log.warn(u'Failed to start controller process')
|
||||||
self.controllers[controller].available = False
|
self.controllers[controller].available = False
|
||||||
self.mediaItem.buildFileMaskString()
|
self.mediaItem.buildFileMaskString()
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Forms in OpenLP are made up of two classes. One class holds all the graphical
|
Forms in OpenLP are made up of two classes. One class holds all the graphical
|
||||||
elements, like buttons and lists, and the other class holds all the functional
|
elements, like buttons and lists, and the other class holds all the functional
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
"""
|
||||||
|
The :mod:`~openlp.plugins.songs.forms.editsongform` module contains the form
|
||||||
|
used to edit songs.
|
||||||
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
@ -42,7 +46,7 @@ from openlp.plugins.songs.forms import EditVerseForm, MediaFilesForm
|
|||||||
from openlp.plugins.songs.lib import SongXML, VerseType, clean_song
|
from openlp.plugins.songs.lib import SongXML, VerseType, clean_song
|
||||||
from openlp.plugins.songs.lib.db import Book, Song, Author, Topic, MediaFile
|
from openlp.plugins.songs.lib.db import Book, Song, Author, Topic, MediaFile
|
||||||
from openlp.plugins.songs.lib.ui import SongStrings
|
from openlp.plugins.songs.lib.ui import SongStrings
|
||||||
from editsongdialog import Ui_EditSongDialog
|
from openlp.plugins.songs.forms.editsongdialog import Ui_EditSongDialog
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -56,7 +60,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
"""
|
"""
|
||||||
Constructor
|
Constructor
|
||||||
"""
|
"""
|
||||||
QtGui.QDialog.__init__(self, parent)
|
super(EditSongForm, self).__init__(parent)
|
||||||
self.mediaitem = mediaitem
|
self.mediaitem = mediaitem
|
||||||
self.song = None
|
self.song = None
|
||||||
# can this be automated?
|
# can this be automated?
|
||||||
@ -113,12 +117,18 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
self.whitespace = re.compile(r'\W+', re.UNICODE)
|
self.whitespace = re.compile(r'\W+', re.UNICODE)
|
||||||
|
|
||||||
def initialise(self):
|
def initialise(self):
|
||||||
|
"""
|
||||||
|
Set up the form for when it is displayed.
|
||||||
|
"""
|
||||||
self.verseEditButton.setEnabled(False)
|
self.verseEditButton.setEnabled(False)
|
||||||
self.verseDeleteButton.setEnabled(False)
|
self.verseDeleteButton.setEnabled(False)
|
||||||
self.authorRemoveButton.setEnabled(False)
|
self.authorRemoveButton.setEnabled(False)
|
||||||
self.topicRemoveButton.setEnabled(False)
|
self.topicRemoveButton.setEnabled(False)
|
||||||
|
|
||||||
def loadAuthors(self):
|
def loadAuthors(self):
|
||||||
|
"""
|
||||||
|
Load the authors from the database into the combobox.
|
||||||
|
"""
|
||||||
authors = self.manager.get_all_objects(Author,
|
authors = self.manager.get_all_objects(Author,
|
||||||
order_by_ref=Author.display_name)
|
order_by_ref=Author.display_name)
|
||||||
self.authorsComboBox.clear()
|
self.authorsComboBox.clear()
|
||||||
@ -132,14 +142,23 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
set_case_insensitive_completer(self.authors, self.authorsComboBox)
|
set_case_insensitive_completer(self.authors, self.authorsComboBox)
|
||||||
|
|
||||||
def loadTopics(self):
|
def loadTopics(self):
|
||||||
|
"""
|
||||||
|
Load the topics into the combobox.
|
||||||
|
"""
|
||||||
self.topics = []
|
self.topics = []
|
||||||
self.__loadObjects(Topic, self.topicsComboBox, self.topics)
|
self.__loadObjects(Topic, self.topicsComboBox, self.topics)
|
||||||
|
|
||||||
def loadBooks(self):
|
def loadBooks(self):
|
||||||
|
"""
|
||||||
|
Load the song books into the combobox
|
||||||
|
"""
|
||||||
self.books = []
|
self.books = []
|
||||||
self.__loadObjects(Book, self.songBookComboBox, self.books)
|
self.__loadObjects(Book, self.songBookComboBox, self.books)
|
||||||
|
|
||||||
def __loadObjects(self, cls, combo, cache):
|
def __loadObjects(self, cls, combo, cache):
|
||||||
|
"""
|
||||||
|
Generically load a set of objects into a cache and a combobox.
|
||||||
|
"""
|
||||||
objects = self.manager.get_all_objects(cls, order_by_ref=cls.name)
|
objects = self.manager.get_all_objects(cls, order_by_ref=cls.name)
|
||||||
combo.clear()
|
combo.clear()
|
||||||
combo.addItem(u'')
|
combo.addItem(u'')
|
||||||
@ -151,6 +170,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
set_case_insensitive_completer(cache, combo)
|
set_case_insensitive_completer(cache, combo)
|
||||||
|
|
||||||
def loadThemes(self, theme_list):
|
def loadThemes(self, theme_list):
|
||||||
|
"""
|
||||||
|
Load the themes into a combobox.
|
||||||
|
"""
|
||||||
self.themeComboBox.clear()
|
self.themeComboBox.clear()
|
||||||
self.themeComboBox.addItem(u'')
|
self.themeComboBox.addItem(u'')
|
||||||
self.themes = theme_list
|
self.themes = theme_list
|
||||||
@ -158,6 +180,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
set_case_insensitive_completer(self.themes, self.themeComboBox)
|
set_case_insensitive_completer(self.themes, self.themeComboBox)
|
||||||
|
|
||||||
def loadMediaFiles(self):
|
def loadMediaFiles(self):
|
||||||
|
"""
|
||||||
|
Load the media files into a combobox.
|
||||||
|
"""
|
||||||
self.audioAddFromMediaButton.setVisible(False)
|
self.audioAddFromMediaButton.setVisible(False)
|
||||||
for plugin in self.parent().pluginManager.plugins:
|
for plugin in self.parent().pluginManager.plugins:
|
||||||
if plugin.name == u'media' and plugin.status == PluginStatus.Active:
|
if plugin.name == u'media' and plugin.status == PluginStatus.Active:
|
||||||
@ -166,6 +191,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
break
|
break
|
||||||
|
|
||||||
def newSong(self):
|
def newSong(self):
|
||||||
|
"""
|
||||||
|
Blank the edit form out in preparation for a new song.
|
||||||
|
"""
|
||||||
log.debug(u'New Song')
|
log.debug(u'New Song')
|
||||||
self.song = None
|
self.song = None
|
||||||
self.initialise()
|
self.initialise()
|
||||||
@ -313,6 +341,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
self.verseListWidget.repaint()
|
self.verseListWidget.repaint()
|
||||||
|
|
||||||
def onAuthorAddButtonClicked(self):
|
def onAuthorAddButtonClicked(self):
|
||||||
|
"""
|
||||||
|
Add the author to the list of authors associated with this song when the button is clicked.
|
||||||
|
"""
|
||||||
item = int(self.authorsComboBox.currentIndex())
|
item = int(self.authorsComboBox.currentIndex())
|
||||||
text = self.authorsComboBox.currentText().strip(u' \r\n\t')
|
text = self.authorsComboBox.currentText().strip(u' \r\n\t')
|
||||||
# This if statement is for OS X, which doesn't seem to work well with
|
# This if statement is for OS X, which doesn't seem to work well with
|
||||||
@ -361,10 +392,16 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
self.authorsListView.addItem(author_item)
|
self.authorsListView.addItem(author_item)
|
||||||
|
|
||||||
def onAuthorsListViewClicked(self):
|
def onAuthorsListViewClicked(self):
|
||||||
|
"""
|
||||||
|
Run a set of actions when an author in the list is selected (mainly enable the delete button).
|
||||||
|
"""
|
||||||
if self.authorsListView.count() > 1:
|
if self.authorsListView.count() > 1:
|
||||||
self.authorRemoveButton.setEnabled(True)
|
self.authorRemoveButton.setEnabled(True)
|
||||||
|
|
||||||
def onAuthorRemoveButtonClicked(self):
|
def onAuthorRemoveButtonClicked(self):
|
||||||
|
"""
|
||||||
|
Remove the author from the list when the delete button is clicked.
|
||||||
|
"""
|
||||||
self.authorRemoveButton.setEnabled(False)
|
self.authorRemoveButton.setEnabled(False)
|
||||||
item = self.authorsListView.currentItem()
|
item = self.authorsListView.currentItem()
|
||||||
row = self.authorsListView.row(item)
|
row = self.authorsListView.row(item)
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from PyQt4 import QtGui, QtCore
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate
|
||||||
from openlp.core.utils import CONTROL_CHARS, locale_direct_compare
|
from openlp.core.utils import CONTROL_CHARS, locale_direct_compare
|
||||||
|
@ -36,7 +36,6 @@ import re
|
|||||||
from sqlalchemy import Column, ForeignKey, Table, types
|
from sqlalchemy import Column, ForeignKey, Table, types
|
||||||
from sqlalchemy.orm import mapper, relation, reconstructor
|
from sqlalchemy.orm import mapper, relation, reconstructor
|
||||||
from sqlalchemy.sql.expression import func
|
from sqlalchemy.sql.expression import func
|
||||||
from PyQt4 import QtCore
|
|
||||||
|
|
||||||
from openlp.core.lib.db import BaseModel, init_db
|
from openlp.core.lib.db import BaseModel, init_db
|
||||||
|
|
||||||
|
@ -30,8 +30,6 @@
|
|||||||
The :mod:`dreambeamimport` module provides the functionality for importing
|
The :mod:`dreambeamimport` module provides the functionality for importing
|
||||||
DreamBeam songs into the OpenLP database.
|
DreamBeam songs into the OpenLP database.
|
||||||
"""
|
"""
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from lxml import etree, objectify
|
from lxml import etree, objectify
|
||||||
@ -46,11 +44,11 @@ class DreamBeamImport(SongImport):
|
|||||||
"""
|
"""
|
||||||
The :class:`DreamBeamImport` class provides the ability to import song files from
|
The :class:`DreamBeamImport` class provides the ability to import song files from
|
||||||
DreamBeam.
|
DreamBeam.
|
||||||
|
|
||||||
An example of DreamBeam xml mark-up::
|
An example of DreamBeam xml mark-up::
|
||||||
|
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<DreamSong xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<DreamSong xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||||
<WordWrap>false</WordWrap>
|
<WordWrap>false</WordWrap>
|
||||||
<Version>0.80</Version>
|
<Version>0.80</Version>
|
||||||
@ -84,7 +82,7 @@ class DreamBeamImport(SongImport):
|
|||||||
|
|
||||||
* \*.xml
|
* \*.xml
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def doImport(self):
|
def doImport(self):
|
||||||
"""
|
"""
|
||||||
Receive a single file or a list of files to import.
|
Receive a single file or a list of files to import.
|
||||||
|
@ -30,8 +30,6 @@
|
|||||||
The :mod:`mediashoutimport` module provides the functionality for importing
|
The :mod:`mediashoutimport` module provides the functionality for importing
|
||||||
a MediaShout database into the OpenLP database.
|
a MediaShout database into the OpenLP database.
|
||||||
"""
|
"""
|
||||||
import re
|
|
||||||
import os
|
|
||||||
import pyodbc
|
import pyodbc
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate
|
||||||
|
@ -31,9 +31,7 @@ The :mod:`songproimport` module provides the functionality for importing SongPro
|
|||||||
songs into the OpenLP database.
|
songs into the OpenLP database.
|
||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
import os
|
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
|
||||||
from openlp.plugins.songs.lib import strip_rtf
|
from openlp.plugins.songs.lib import strip_rtf
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
|
||||||
|
@ -107,13 +107,13 @@ class WowImport(SongImport):
|
|||||||
"""
|
"""
|
||||||
if isinstance(self.importSource, list):
|
if isinstance(self.importSource, list):
|
||||||
self.importWizard.progressBar.setMaximum(len(self.importSource))
|
self.importWizard.progressBar.setMaximum(len(self.importSource))
|
||||||
for file in self.importSource:
|
for source in self.importSource:
|
||||||
if self.stopImportFlag:
|
if self.stopImportFlag:
|
||||||
return
|
return
|
||||||
self.setDefaults()
|
self.setDefaults()
|
||||||
song_data = open(file, 'rb')
|
song_data = open(source, 'rb')
|
||||||
if song_data.read(19) != u'WoW File\nSong Words':
|
if song_data.read(19) != u'WoW File\nSong Words':
|
||||||
self.logError(file, unicode(translate('SongsPlugin.WordsofWorshipSongImport',
|
self.logError(source, unicode(translate('SongsPlugin.WordsofWorshipSongImport',
|
||||||
('Invalid Words of Worship song file. Missing "Wow File\\nSong Words" header.'))))
|
('Invalid Words of Worship song file. Missing "Wow File\\nSong Words" header.'))))
|
||||||
continue
|
continue
|
||||||
# Seek to byte which stores number of blocks in the song
|
# Seek to byte which stores number of blocks in the song
|
||||||
@ -121,7 +121,7 @@ class WowImport(SongImport):
|
|||||||
no_of_blocks = ord(song_data.read(1))
|
no_of_blocks = ord(song_data.read(1))
|
||||||
song_data.seek(66)
|
song_data.seek(66)
|
||||||
if song_data.read(16) != u'CSongDoc::CBlock':
|
if song_data.read(16) != u'CSongDoc::CBlock':
|
||||||
self.logError(file, unicode(translate('SongsPlugin.WordsofWorshipSongImport',
|
self.logError(source, unicode(translate('SongsPlugin.WordsofWorshipSongImport',
|
||||||
('Invalid Words of Worship song file. Missing "CSongDoc::CBlock" string.'))))
|
('Invalid Words of Worship song file. Missing "CSongDoc::CBlock" string.'))))
|
||||||
continue
|
continue
|
||||||
# Seek to the beginning of the first block
|
# Seek to the beginning of the first block
|
||||||
@ -150,9 +150,9 @@ class WowImport(SongImport):
|
|||||||
copyright_length = ord(song_data.read(1))
|
copyright_length = ord(song_data.read(1))
|
||||||
if copyright_length:
|
if copyright_length:
|
||||||
self.addCopyright(unicode(song_data.read(copyright_length), u'cp1252'))
|
self.addCopyright(unicode(song_data.read(copyright_length), u'cp1252'))
|
||||||
file_name = os.path.split(file)[1]
|
file_name = os.path.split(source)[1]
|
||||||
# Get the song title
|
# Get the song title
|
||||||
self.title = file_name.rpartition(u'.')[0]
|
self.title = file_name.rpartition(u'.')[0]
|
||||||
song_data.close()
|
song_data.close()
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(file)
|
self.logError(source)
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
"""
|
||||||
|
The :mod:`~openlp.plugins.songs.songsplugin` module contains the Plugin class
|
||||||
|
for the Songs plugin.
|
||||||
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
@ -38,6 +38,7 @@ modules, simply run this script::
|
|||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
is_win = sys.platform.startswith('win')
|
is_win = sys.platform.startswith('win')
|
||||||
|
|
||||||
@ -89,15 +90,13 @@ OPTIONAL_MODULES = [
|
|||||||
w = sys.stdout.write
|
w = sys.stdout.write
|
||||||
|
|
||||||
def check_vers(version, required, text):
|
def check_vers(version, required, text):
|
||||||
if type(version) is str:
|
if type(version) is not str:
|
||||||
version = version.split('.')
|
version = '.'.join(map(str, version))
|
||||||
version = map(int, version)
|
if type(required) is not str:
|
||||||
if type(required) is str:
|
required = '.'.join(map(str, required))
|
||||||
required = required.split('.')
|
w(' %s >= %s ... ' % (text, required))
|
||||||
required = map(int, required)
|
if LooseVersion(version) >= LooseVersion(required):
|
||||||
w(' %s >= %s ... ' % (text, '.'.join(map(str, required))))
|
w(version + os.linesep)
|
||||||
if version >= required:
|
|
||||||
w('.'.join(map(str, version)) + os.linesep)
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
w('FAIL' + os.linesep)
|
w('FAIL' + os.linesep)
|
||||||
|
BIN
tests/functional/openlp_core_lib/resources/church.jpg
Normal file
BIN
tests/functional/openlp_core_lib/resources/church.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 213 KiB |
@ -3,7 +3,7 @@ Package to test the openlp.core.lib package.
|
|||||||
"""
|
"""
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from mock import MagicMock, patch, call
|
from mock import MagicMock, patch
|
||||||
|
|
||||||
from openlp.core.lib import str_to_bool, translate, check_directory_exists, get_text_file_string, build_icon
|
from openlp.core.lib import str_to_bool, translate, check_directory_exists, get_text_file_string, build_icon
|
||||||
|
|
||||||
|
163
tests/functional/openlp_core_lib/test_serviceitem.py
Normal file
163
tests/functional/openlp_core_lib/test_serviceitem.py
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
"""
|
||||||
|
Package to test the openlp.core.lib package.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
|
from mock import MagicMock
|
||||||
|
from openlp.core.lib import ServiceItem
|
||||||
|
|
||||||
|
VERSE = u'The Lord said to {r}Noah{/r}: \n'\
|
||||||
|
'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n'\
|
||||||
|
'The Lord said to {g}Noah{/g}:\n'\
|
||||||
|
'There\'s gonna be a {st}floody{/st}, {it}floody{/it}\n'\
|
||||||
|
'Get those children out of the muddy, muddy \n'\
|
||||||
|
'{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}'\
|
||||||
|
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
|
||||||
|
FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456']
|
||||||
|
|
||||||
|
TESTPATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'resources'))
|
||||||
|
|
||||||
|
class TestServiceItem(TestCase):
|
||||||
|
|
||||||
|
def serviceitem_basic_test(self):
|
||||||
|
"""
|
||||||
|
Test the Service Item basic test
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service item
|
||||||
|
|
||||||
|
# WHEN:A service item is created (without a plugin)
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
|
||||||
|
# THEN: We should get back a valid service item
|
||||||
|
assert service_item.is_valid is True, u'The new service item should be valid'
|
||||||
|
assert service_item.missing_frames() is True, u'There should not be any frames in the service item'
|
||||||
|
|
||||||
|
def serviceitem_add_text_test(self):
|
||||||
|
"""
|
||||||
|
Test the Service Item add text test
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service item
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
|
||||||
|
# WHEN: adding text to a service item
|
||||||
|
service_item.add_from_text(VERSE)
|
||||||
|
service_item.raw_footer = FOOTER
|
||||||
|
|
||||||
|
# THEN: We should get back a valid service item
|
||||||
|
assert service_item.is_valid is True, u'The new service item should be valid'
|
||||||
|
assert service_item.missing_frames() is False, u'check frames loaded '
|
||||||
|
|
||||||
|
# GIVEN: A service item with text
|
||||||
|
mocked_renderer = MagicMock()
|
||||||
|
mocked_renderer.format_slide.return_value = [VERSE]
|
||||||
|
service_item.renderer = mocked_renderer
|
||||||
|
|
||||||
|
# WHEN: Render called
|
||||||
|
assert len(service_item._display_frames) == 0, u'A blank Service Item with no display frames'
|
||||||
|
service_item.render(True)
|
||||||
|
|
||||||
|
# THEN: We should have a page of output.
|
||||||
|
assert len(service_item._display_frames) == 1, u'A valid rendered Service Item has 1 display frame'
|
||||||
|
assert service_item.get_rendered_frame(0) == VERSE.split(u'\n')[0], u'A output has rendered correctly.'
|
||||||
|
|
||||||
|
def serviceitem_add_image_test(self):
|
||||||
|
"""
|
||||||
|
Test the Service Item add image test
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service item and a mocked renderer
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
service_item.name = u'test'
|
||||||
|
mocked_renderer = MagicMock()
|
||||||
|
service_item.renderer = mocked_renderer
|
||||||
|
|
||||||
|
# WHEN: adding image to a service item
|
||||||
|
test_image = os.path.join(TESTPATH, u'church.jpg')
|
||||||
|
service_item.add_from_image(test_image, u'Image Title')
|
||||||
|
|
||||||
|
# THEN: We should get back a valid service item
|
||||||
|
assert service_item.is_valid is True, u'The new service item should be valid'
|
||||||
|
assert len(service_item._display_frames) == 0, u'The service item has no display frames'
|
||||||
|
|
||||||
|
# THEN: We should have a page of output.
|
||||||
|
assert len(service_item._raw_frames) == 1, u'A valid rendered Service Item has display frames'
|
||||||
|
assert service_item.get_rendered_frame(0) == test_image
|
||||||
|
|
||||||
|
# WHEN: adding a second image to a service item
|
||||||
|
service_item.add_from_image(test_image, u'Image1 Title')
|
||||||
|
|
||||||
|
# THEN: We should have an increased page of output.
|
||||||
|
assert len(service_item._raw_frames) == 2, u'A valid rendered Service Item has display frames'
|
||||||
|
assert service_item.get_rendered_frame(0) == test_image
|
||||||
|
assert service_item.get_rendered_frame(0) == service_item.get_rendered_frame(1)
|
||||||
|
|
||||||
|
# WHEN requesting a saved service item
|
||||||
|
service = service_item.get_service_repr(True)
|
||||||
|
|
||||||
|
# THEN: We should have two parts of the service.
|
||||||
|
assert len(service) == 2, u'A saved service has two parts'
|
||||||
|
assert service[u'header'][u'name'] == u'test' , u'A test plugin was returned'
|
||||||
|
assert service[u'data'][0][u'title'] == u'Image Title' , u'The first title name matches the request'
|
||||||
|
assert service[u'data'][0][u'path'] == test_image , u'The first image name matches'
|
||||||
|
assert service[u'data'][0][u'title'] != service[u'data'][1][u'title'], \
|
||||||
|
u'The individual titles should not match'
|
||||||
|
assert service[u'data'][0][u'path'] == service[u'data'][1][u'path'], u'The file paths should match'
|
||||||
|
|
||||||
|
# WHEN validating a service item
|
||||||
|
service_item.validate_item([u'jpg'])
|
||||||
|
|
||||||
|
# THEN the service item should be valid
|
||||||
|
assert service_item.is_valid is True, u'The new service item should be valid'
|
||||||
|
|
||||||
|
# WHEN: adding a second image to a service item
|
||||||
|
service_item.add_from_image(u'resources/church1.jpg', u'Image1 Title')
|
||||||
|
|
||||||
|
# WHEN validating a service item
|
||||||
|
service_item.validate_item([u'jpg'])
|
||||||
|
|
||||||
|
# THEN the service item should be valid
|
||||||
|
assert service_item.is_valid is False, u'The service item is not valid due to validation changes'
|
||||||
|
|
||||||
|
def serviceitem_add_command_test(self):
|
||||||
|
"""
|
||||||
|
Test the Service Item add command test
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service item and a mocked renderer
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
service_item.name = u'test'
|
||||||
|
mocked_renderer = MagicMock()
|
||||||
|
service_item.renderer = mocked_renderer
|
||||||
|
|
||||||
|
# WHEN: adding image to a service item
|
||||||
|
test_file = os.path.join(TESTPATH, u'church.jpg')
|
||||||
|
service_item.add_from_command(TESTPATH, u'church.jpg', test_file)
|
||||||
|
|
||||||
|
# THEN: We should get back a valid service item
|
||||||
|
assert service_item.is_valid is True, u'The new service item should be valid'
|
||||||
|
assert len(service_item._display_frames) == 0, u'The service item has no display frames '
|
||||||
|
|
||||||
|
# THEN: We should have a page of output.
|
||||||
|
assert len(service_item._raw_frames) == 1, u'A valid rendered Service Item has one raw frame'
|
||||||
|
assert service_item.get_rendered_frame(0) == test_file, u'The image matches the input'
|
||||||
|
|
||||||
|
# WHEN requesting a saved service item
|
||||||
|
service = service_item.get_service_repr(True)
|
||||||
|
|
||||||
|
# THEN: We should have two parts of the service.
|
||||||
|
assert len(service) == 2, u'A saved service has two parts'
|
||||||
|
assert service[u'header'][u'name'] == u'test' , u'A test plugin'
|
||||||
|
assert service[u'data'][0][u'title'] == u'church.jpg' , u'The first title name '
|
||||||
|
assert service[u'data'][0][u'path'] == TESTPATH , u'The first image name'
|
||||||
|
assert service[u'data'][0][u'image'] == test_file , u'The first image name'
|
||||||
|
|
||||||
|
# WHEN validating a service item
|
||||||
|
service_item.validate_item([u'jpg'])
|
||||||
|
|
||||||
|
# THEN the service item should be valid
|
||||||
|
assert service_item.is_valid is True, u'The service item is valid'
|
||||||
|
|
||||||
|
# WHEN validating a service item with a different suffix
|
||||||
|
service_item.validate_item([u'png'])
|
||||||
|
|
||||||
|
# THEN the service item should not be valid
|
||||||
|
assert service_item.is_valid is False, u'The service item is not valid'
|
48
tests/functional/openlp_core_ui/starttimedialog.py
Normal file
48
tests/functional/openlp_core_ui/starttimedialog.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
"""
|
||||||
|
Package to test the openlp.core.ui package.
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
|
from mock import MagicMock
|
||||||
|
from openlp.core.ui import starttimeform
|
||||||
|
from PyQt4 import QtCore, QtGui, QtTest
|
||||||
|
|
||||||
|
class TestStartTimeDialog(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create the UI
|
||||||
|
"""
|
||||||
|
self.app = QtGui.QApplication(sys.argv)
|
||||||
|
self.window = QtGui.QMainWindow()
|
||||||
|
self.form = starttimeform.StartTimeForm(self.window)
|
||||||
|
|
||||||
|
def ui_defaults_test(self):
|
||||||
|
"""
|
||||||
|
Test StartTimeDialog defaults
|
||||||
|
"""
|
||||||
|
self.assertEqual(self.form.hourSpinBox.minimum(), 0)
|
||||||
|
self.assertEqual(self.form.hourSpinBox.maximum(), 4)
|
||||||
|
self.assertEqual(self.form.minuteSpinBox.minimum(), 0)
|
||||||
|
self.assertEqual(self.form.minuteSpinBox.maximum(), 59)
|
||||||
|
self.assertEqual(self.form.secondSpinBox.minimum(), 0)
|
||||||
|
self.assertEqual(self.form.secondSpinBox.maximum(), 59)
|
||||||
|
self.assertEqual(self.form.hourFinishSpinBox.minimum(), 0)
|
||||||
|
self.assertEqual(self.form.hourFinishSpinBox.maximum(), 4)
|
||||||
|
self.assertEqual(self.form.minuteFinishSpinBox.minimum(), 0)
|
||||||
|
self.assertEqual(self.form.minuteFinishSpinBox.maximum(), 59)
|
||||||
|
self.assertEqual(self.form.secondFinishSpinBox.minimum(), 0)
|
||||||
|
self.assertEqual(self.form.secondFinishSpinBox.maximum(), 59)
|
||||||
|
|
||||||
|
def time_display_test(self):
|
||||||
|
"""
|
||||||
|
Test StartTimeDialog display initialisation
|
||||||
|
"""
|
||||||
|
#GIVEN: A service item with with time
|
||||||
|
mocked_serviceitem = MagicMock()
|
||||||
|
mocked_serviceitem.start_time = 61
|
||||||
|
mocked_serviceitem.end_time = 3701
|
||||||
|
|
||||||
|
self.form.item = mocked_serviceitem
|
||||||
|
#self.form.exec_()
|
BIN
tests/functional/resources/church.jpg
Normal file
BIN
tests/functional/resources/church.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 213 KiB |
@ -34,4 +34,4 @@ from openlp.core.ui.mainwindow import MainWindow
|
|||||||
def test_start_app(openlpapp):
|
def test_start_app(openlpapp):
|
||||||
assert type(openlpapp) == OpenLP
|
assert type(openlpapp) == OpenLP
|
||||||
assert type(openlpapp.mainWindow) == MainWindow
|
assert type(openlpapp.mainWindow) == MainWindow
|
||||||
assert unicode(openlpapp.mainWindow.windowTitle()) == u'OpenLP 2.0'
|
assert unicode(openlpapp.mainWindow.windowTitle()) == u'OpenLP 2.1'
|
||||||
|
Loading…
Reference in New Issue
Block a user