This commit is contained in:
Tim Bentley 2012-03-25 07:25:37 +01:00
commit 120c6a0acb
54 changed files with 65540 additions and 22438 deletions

View File

@ -22,3 +22,4 @@ openlp/core/resources.py.old
resources/windows/warnOpenLP.txt
openlp.cfg
.idea
openlp.pro

View File

@ -33,7 +33,8 @@ from urllib import quote_plus as urlquote
from PyQt4 import QtCore
from sqlalchemy import Table, MetaData, Column, types, create_engine
from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError
from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError, \
OperationalError
from sqlalchemy.orm import scoped_session, sessionmaker, mapper
from sqlalchemy.pool import NullPool

View File

@ -458,13 +458,18 @@ def build_lyrics_format_css(theme, width, height):
# fix tag incompatibilities
if theme.display_horizontal_align == HorizontalType.Justify:
justify = u''
if theme.display_vertical_align == VerticalType.Bottom:
padding_bottom = u'0.5em'
else:
padding_bottom = u'0'
lyrics = u'%s word-wrap: break-word; ' \
'text-align: %s; vertical-align: %s; font-family: %s; ' \
'font-size: %spt; color: %s; line-height: %d%%; margin: 0;' \
'padding: 0; padding-left: %spx; width: %spx; height: %spx; ' % \
'padding: 0; padding-bottom: %s; padding-left: %spx; width: %spx;' \
'height: %spx; ' % \
(justify, align, valign, theme.font_main_name, theme.font_main_size,
theme.font_main_color, 100 + int(theme.font_main_line_adjustment),
left_margin, width, height)
padding_bottom, left_margin, width, height)
if theme.font_main_outline:
if webkit_version() <= 534.3:
lyrics += u' letter-spacing: 1px;'

View File

@ -166,7 +166,7 @@ class ImageManager(QtCore.QObject):
self.height = current_screen[u'size'].height()
# Mark the images as dirty for a rebuild by setting the image and byte
# stream to None.
for key, image in self._cache.iteritems():
for image in self._cache.values():
self._reset_image(image)
def update_images(self, image_type, background):
@ -176,7 +176,7 @@ class ImageManager(QtCore.QObject):
log.debug(u'update_images')
# Mark the images as dirty for a rebuild by setting the image and byte
# stream to None.
for key, image in self._cache.iteritems():
for image in self._cache.values():
if image.source == image_type:
image.background = background
self._reset_image(image)
@ -188,7 +188,7 @@ class ImageManager(QtCore.QObject):
log.debug(u'update_images')
# Mark the images as dirty for a rebuild by setting the image and byte
# stream to None.
for key, image in self._cache.iteritems():
for image in self._cache.values():
if image.source == image_type and image.name == name:
image.background = background
self._reset_image(image)

View File

@ -289,7 +289,7 @@ class Renderer(object):
def _calculate_default(self):
"""
Calculate the default dimentions of the screen.
Calculate the default dimensions of the screen.
"""
screen_size = self.screens.current[u'size']
self.width = screen_size.width()
@ -380,6 +380,7 @@ class Renderer(object):
(build_lyrics_format_css(self.theme_data, self.page_width,
self.page_height), build_lyrics_outline_css(self.theme_data))
self.web.setHtml(html)
self.empty_height = self.web_frame.contentsSize().height()
def _paginate_slide(self, lines, line_end):
"""
@ -600,7 +601,7 @@ class Renderer(object):
"""
self.web_frame.evaluateJavaScript(u'show_text("%s")' %
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
return self.web_frame.contentsSize().height() <= self.page_height
return self.web_frame.contentsSize().height() <= self.empty_height
def _words_split(self, line):
"""

View File

@ -300,6 +300,7 @@ class ServiceItem(object):
``path``
Defaults to *None*. Any path data, usually for images.
"""
log.debug(u'set_from_service called with path %s' % path)
header = serviceitem[u'serviceitem'][u'header']
self.title = header[u'title']
self.name = header[u'name']

View File

@ -53,13 +53,10 @@ class AdvancedTab(SettingsTab):
self.defaultServiceMinute = 0
self.defaultServiceName = unicode(translate('OpenLP.AdvancedTab',
'Service %Y-%m-%d %H-%M',
'This is the default default service name template, which can be '
'found under Advanced in Settings, Configure OpenLP. Please do not '
'include any of the following characters: /\\?*|<>\[\]":+\n'
'You can use any of the directives as shown on page '
'http://docs.python.org/library/datetime.html'
'#strftime-strptime-behavior , but if possible, please keep '
'the resulting string sortable by name.'))
'This may not contain any of the following characters: '
'/\\?*|<>\[\]":+\n'
'See http://docs.python.org/library/datetime.html'
'#strftime-strptime-behavior for more information.'))
self.defaultImage = u':/graphics/openlp-splash-screen.png'
self.defaultColor = u'#ffffff'
self.icon_path = u':/system/system_settings.png'

View File

@ -295,7 +295,8 @@ class GeneralTab(SettingsTab):
QtCore.QVariant(False)).toBool())
self.timeoutSpinBox.setValue(settings.value(u'loop delay',
QtCore.QVariant(5)).toInt()[0])
self.monitorRadioButton.setChecked(not settings.value(u'override position',
self.monitorRadioButton.setChecked(
not settings.value(u'override position',
QtCore.QVariant(False)).toBool())
self.overrideRadioButton.setChecked(settings.value(u'override position',
QtCore.QVariant(False)).toBool())
@ -313,11 +314,14 @@ class GeneralTab(SettingsTab):
u'audio repeat list', QtCore.QVariant(False)).toBool())
settings.endGroup()
self.monitorComboBox.setDisabled(self.overrideRadioButton.isChecked())
self.displayOnMonitorCheck.setDisabled(self.overrideRadioButton.isChecked())
self.displayOnMonitorCheck.setDisabled(
self.overrideRadioButton.isChecked())
self.customXValueEdit.setEnabled(self.overrideRadioButton.isChecked())
self.customYValueEdit.setEnabled(self.overrideRadioButton.isChecked())
self.customHeightValueEdit.setEnabled(self.overrideRadioButton.isChecked())
self.customWidthValueEdit.setEnabled(self.overrideRadioButton.isChecked())
self.customHeightValueEdit.setEnabled(
self.overrideRadioButton.isChecked())
self.customWidthValueEdit.setEnabled(
self.overrideRadioButton.isChecked())
self.display_changed = False
settings.beginGroup(self.settingsSection)

View File

@ -24,17 +24,21 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
from PyQt4 import QtCore
log = logging.getLogger(__name__)
class MediaState(object):
"""
An enumeration for possible States of the Media Player (copied partially
from Phonon::State)
An enumeration for possible States of the Media Player
"""
Loading = 0
Stopped = 1
Off = 0
Loaded = 1
Playing = 2
Paused = 4
Off = 6
Paused = 3
Stopped = 4
class MediaType(object):
@ -62,4 +66,48 @@ class MediaInfo(object):
end_time = 0
media_type = MediaType()
def get_media_players():
"""
This method extract the configured media players and overridden player from
the settings
``players_list``
this is a python list with all active media players
``overridden_player``
here an special media player is choosen for all media actions
"""
log.debug(u'get_media_players')
players = unicode(QtCore.QSettings().value(u'media/players').toString())
if not players:
players = u'webkit'
reg_ex = QtCore.QRegExp(".*\[(.*)\].*")
if QtCore.QSettings().value(u'media/override player',
QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0] == QtCore.Qt.Checked:
if reg_ex.exactMatch(players):
overridden_player = u'%s' % reg_ex.cap(1)
else:
overridden_player = u'auto'
else:
overridden_player = u''
players_list = players.replace(u'[', u'').replace(u']', u'').split(u',')
return players_list, overridden_player
def set_media_players(players_list, overridden_player=u'auto'):
"""
This method saves the configured media players and overridden player to the
settings
``players_list``
this is a python list with all active media players
``overridden_player``
here an special media player is choosen for all media actions
"""
log.debug(u'set_media_players')
players = u','.join(players_list)
if QtCore.QSettings().value(u'media/override player',
QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0] == \
QtCore.Qt.Checked and overridden_player != u'auto':
players = players.replace(overridden_player, u'[%s]' % overridden_player)
QtCore.QSettings().setValue(u'media/players', QtCore.QVariant(players))
from mediacontroller import MediaController

View File

@ -32,7 +32,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, Receiver, translate
from openlp.core.lib.mediaplayer import MediaPlayer
from openlp.core.lib.ui import 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
from openlp.core.utils import AppLocation
log = logging.getLogger(__name__)
@ -47,7 +48,6 @@ class MediaController(object):
self.parent = parent
self.mediaPlayers = {}
self.controller = []
self.overriddenPlayer = ''
self.curDisplayMediaPlayer = {}
# Timer for video state
self.timer = QtCore.QTimer()
@ -73,8 +73,6 @@ class MediaController(object):
QtCore.SIGNAL(u'media_blank'), self.video_blank)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_unblank'), self.video_unblank)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_override_player'), self.override_player)
# Signals for background video
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'songs_hide'), self.video_hide)
@ -84,11 +82,7 @@ class MediaController(object):
QtCore.SIGNAL(u'mediaitem_media_rebuild'), self.set_active_players)
def set_active_players(self):
playerSettings = str(QtCore.QSettings().value(u'media/players',
QtCore.QVariant(u'webkit')).toString())
if len(playerSettings) == 0:
playerSettings = u'webkit'
savedPlayers = playerSettings.split(u',')
savedPlayers = get_media_players()[0]
for player in self.mediaPlayers.keys():
if player in savedPlayers:
self.mediaPlayers[player].isActive = True
@ -129,18 +123,14 @@ class MediaController(object):
controller = controller_class(self)
self.register_controllers(controller)
if self.mediaPlayers:
playerSettings = str(QtCore.QSettings().value(u'media/players',
QtCore.QVariant(u'webkit')).toString())
savedPlayers = playerSettings.split(u',')
savedPlayers, overriddenPlayer = get_media_players()
invalidMediaPlayers = [mediaPlayer for mediaPlayer in savedPlayers \
if not mediaPlayer in self.mediaPlayers or \
not self.mediaPlayers[mediaPlayer].check_available()]
if len(invalidMediaPlayers) > 0:
for invalidPlayer in invalidMediaPlayers:
savedPlayers.remove(invalidPlayer)
newPlayerSetting = u','.join(savedPlayers)
QtCore.QSettings().setValue(u'media/players',
QtCore.QVariant(newPlayerSetting))
set_media_players(savedPlayers, overriddenPlayer)
self.set_active_players()
return True
else:
@ -286,7 +276,8 @@ class MediaController(object):
controller.mediabar.setVisible(value)
if controller.isLive and controller.display:
if self.curDisplayMediaPlayer and value:
if self.curDisplayMediaPlayer[controller.display] != self.mediaPlayers[u'webkit']:
if self.curDisplayMediaPlayer[controller.display] != \
self.mediaPlayers[u'webkit']:
controller.display.setTransparency(False)
# Special controls: Here media type specific Controls will be enabled
# (e.g. for DVD control, ...)
@ -366,13 +357,9 @@ class MediaController(object):
"""
Select the correct media Player type from the prioritized Player list
"""
playerSettings = str(QtCore.QSettings().value(u'media/players',
QtCore.QVariant(u'webkit')).toString())
usedPlayers = playerSettings.split(u',')
if QtCore.QSettings().value(u'media/override player',
QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked:
if self.overriddenPlayer != '':
usedPlayers = [self.overriddenPlayer]
usedPlayers, overriddenPlayer = get_media_players()
if overriddenPlayer and overriddenPlayer != u'auto':
usedPlayers = [overriddenPlayer]
if controller.media_info.file_info.isFile():
suffix = u'*.%s' % \
controller.media_info.file_info.suffix().toLower()
@ -583,16 +570,6 @@ class MediaController(object):
video_list.append(item)
return video_list
def override_player(self, override_player_index):
playerSettings = str(QtCore.QSettings().value(u'media/players',
QtCore.QVariant(u'webkit')).toString())
usedPlayers = playerSettings.split(u',')
if override_player_index >= 0 and \
override_player_index < len(usedPlayers):
self.overridenPlayer = usedPlayers[override_player_index]
else:
self.overriddenPlayer = ''
def finalise(self):
self.timer.stop()
for controller in self.controller:

View File

@ -405,7 +405,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
# Only continue when we include the song's text.
if not self.slideTextCheckBox.isChecked():
return
for index, item in enumerate(self.serviceManager.serviceItems):
for item in self.serviceManager.serviceItems:
# Trigger Audit requests
Receiver.send_message(u'print_service_started',
[item[u'service_item']])

View File

@ -461,7 +461,7 @@ class ServiceManager(QtGui.QWidget):
log.debug(temp_file_name)
path_file_name = unicode(self.fileName())
path, file_name = os.path.split(path_file_name)
basename, extension = os.path.splitext(file_name)
basename = os.path.splitext(file_name)[0]
service_file_name = '%s.osd' % basename
log.debug(u'ServiceManager.saveFile - %s', path_file_name)
SettingsManager.set_last_dir(
@ -483,8 +483,7 @@ class ServiceManager(QtGui.QWidget):
for i, filename in \
enumerate(service_item[u'header'][u'background_audio']):
new_file = os.path.join(u'audio',
item[u'service_item']._uuid,
os.path.split(filename)[1])
item[u'service_item']._uuid, filename)
audio_files.append((filename, new_file))
service_item[u'header'][u'background_audio'][i] = new_file
# Add the service item to the service.
@ -610,16 +609,11 @@ class ServiceManager(QtGui.QWidget):
time = time.replace(hour=service_hour, minute=service_minute)
default_pattern = unicode(QtCore.QSettings().value(
u'advanced/default service name',
translate('OpenLP.AdvancedTab',
'Service %Y-%m-%d %H-%M',
'This is the default default service name template, which can '
'be found under Advanced in Settings, Configure OpenLP. '
'Please do not include any of the following characters: '
'/\\?*|<>\[\]":+\n'
'You can use any of the directives as shown on page '
'http://docs.python.org/library/datetime.html'
'#strftime-strptime-behavior , but if possible, please keep '
'the resulting string sortable by name.')).toString())
translate('OpenLP.AdvancedTab', 'Service %Y-%m-%d %H-%M',
'This may not contain any of the following characters: '
'/\\?*|<>\[\]":+\nSee http://docs.python.org/library/'
'datetime.html#strftime-strptime-behavior for more '
'information.')).toString())
default_filename = time.strftime(default_pattern)
else:
default_filename = u''
@ -1359,15 +1353,15 @@ class ServiceManager(QtGui.QWidget):
Handle of the event pint passed
"""
link = event.mimeData()
if event.mimeData().hasUrls():
if link.hasUrls():
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
for url in event.mimeData().urls():
for url in link.urls():
filename = unicode(url.toLocalFile())
if filename.endswith(u'.osz'):
self.onLoadServiceClicked(filename)
elif event.mimeData().hasText():
plugin = unicode(event.mimeData().text())
elif link.hasText():
plugin = unicode(link.text())
item = self.serviceManagerList.itemAt(event.pos())
# ServiceManager started the drag and drop
if plugin == u'ServiceManager':

View File

@ -57,7 +57,7 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
def exec_(self):
# load all the settings
self.settingListWidget.clear()
for tabIndex in range(0, self.stackedLayout.count() + 1):
while self.stackedLayout.count():
# take at 0 and the rest shuffle up.
self.stackedLayout.takeAt(0)
self.insertTab(self.generalTab, 0, PluginStatus.Active)

View File

@ -563,7 +563,8 @@ class SlideController(Controller):
Receiver.send_message('servicemanager_previous_item')
elif keypressCommand == ServiceItemAction.PreviousLastSlide:
# Go to the last slide of the previous item
Receiver.send_message('servicemanager_previous_item', u'last slide')
Receiver.send_message('servicemanager_previous_item',
u'last slide')
else:
Receiver.send_message('servicemanager_next_item')
self.keypress_loop = False
@ -1190,7 +1191,8 @@ class SlideController(Controller):
if self.slide_limits == SlideLimits.Wrap:
row = self.previewListWidget.rowCount() - 1
elif self.isLive and self.slide_limits == SlideLimits.Next:
self.keypress_queue.append(ServiceItemAction.PreviousLastSlide)
self.keypress_queue.append(
ServiceItemAction.PreviousLastSlide)
self._process_queue()
return
else:

View File

@ -153,7 +153,6 @@ class ThemeManager(QtGui.QWidget):
Import new themes downloaded by the first time wizard
"""
Receiver.send_message(u'cursor_busy')
encoding = get_filesystem_encoding()
files = SettingsManager.get_files(self.settingsSection, u'.otz')
for file in files:
file = os.path.join(self.path, file)

View File

@ -53,6 +53,8 @@ APPLICATION_VERSION = {}
IMAGES_FILTER = None
UNO_CONNECTION_TYPE = u'pipe'
#UNO_CONNECTION_TYPE = u'socket'
CONTROL_CHARS = re.compile(r'[\x00-\x1F\x7F-\x9F]', re.UNICODE)
INVALID_FILE_CHARS = re.compile(r'[\\/:\*\?"<>\|\+\[\]%]', re.UNICODE)
VERSION_SPLITTER = re.compile(r'([0-9]+).([0-9]+).([0-9]+)(?:-bzr([0-9]+))?')
class VersionThread(QtCore.QThread):
@ -400,7 +402,7 @@ def clean_filename(filename):
"""
if not isinstance(filename, unicode):
filename = unicode(filename, u'utf-8')
return re.sub(r'[/\\?*|<>\[\]":<>+%\n]+', u'_', filename).strip(u'_')
return INVALID_FILE_CHARS.sub(u'_', CONTROL_CHARS.sub(u'', filename))
def delete_file(file_path_name):
"""

View File

@ -27,7 +27,7 @@
import logging
from PyQt4 import QtCore, QtGui
from PyQt4 import QtGui
from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.ui import create_action, UiStrings

View File

@ -183,13 +183,8 @@ def update_reference_separators():
"""
default_separators = unicode(translate('BiblesPlugin',
':|v|V|verse|verses;;-|to;;,|and;;end',
'This are 4 values seperated each by two semicolons representing the '
'seperators for parsing references. This values are verse separators, '
'range separators, list separators and end mark. Alternative values '
'to be seperated by a vertical bar "|". In this case the first value '
'is the default and used for the display format. If a semicolon should '
'be used you have to give an alternative separator afterwards to allow '
'OpenLP correct splitting of the translation.')).split(u';;')
'Double-semicolon delimited separators for parsing references. '
'Consult the developers for further information.')).split(u';;')
settings = QtCore.QSettings()
settings.beginGroup(u'bibles')
custom_separators = [

View File

@ -177,7 +177,7 @@ class CustomMediaItem(MediaManagerItem):
UiStrings().ConfirmDelete,
translate('CustomPlugin.MediaItem',
'Are you sure you want to delete the %n selected custom'
' slides(s)?', '',
' slide(s)?', '',
QtCore.QCoreApplication.CodecForTr, len(items)),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No),

View File

@ -189,7 +189,7 @@ class ImageMediaItem(MediaManagerItem):
# Continue with the existing images.
for bitem in items:
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
(path, name) = os.path.split(filename)
name = os.path.split(filename)[1]
service_item.add_from_image(filename, name, background)
return True
@ -220,7 +220,7 @@ class ImageMediaItem(MediaManagerItem):
bitem = self.listView.item(item.row())
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
if os.path.exists(filename):
(path, name) = os.path.split(filename)
name = os.path.split(filename)[1]
if self.plugin.liveController.display.directImage(name,
filename, background):
self.resetAction.setVisible(True)

View File

@ -37,6 +37,7 @@ from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
media_item_combo_box
from openlp.core.ui import Controller, Display
from openlp.core.ui.media import get_media_players, set_media_players
log = logging.getLogger(__name__)
@ -142,8 +143,11 @@ class MediaMediaItem(MediaManagerItem):
self.overridePlayerChanged)
def overridePlayerChanged(self, index):
# index - 1, because the first item is "Automatic".
Receiver.send_message(u'media_override_player', index - 1)
player = get_media_players()[0]
if index == 0:
set_media_players(player)
else:
set_media_players(player, player[index-1])
def onResetClick(self):
"""
@ -239,29 +243,31 @@ class MediaMediaItem(MediaManagerItem):
self.plugin.mediaController.setup_display( \
self.mediaController.previewDisplay)
def populateDisplayTypes(self):
"""
Load the combobox with the enabled media players,
allowing user to select a specific player if settings allow
"""
# block signals to avoid unnecessary overridePlayerChanged Signales
# while combo box creation
self.displayTypeComboBox.blockSignals(True)
self.displayTypeComboBox.clear()
playerSettings = str(QtCore.QSettings().value(u'media/players',
QtCore.QVariant(u'webkit')).toString())
usedPlayers = playerSettings.split(u',')
usedPlayers, overridePlayer = get_media_players()
mediaPlayers = self.plugin.mediaController.mediaPlayers
currentIndex = 0
for player in usedPlayers:
# load the drop down selection
self.displayTypeComboBox.addItem(mediaPlayers[player].original_name)
if overridePlayer == player:
currentIndex = len(self.displayTypeComboBox)
if self.displayTypeComboBox.count() > 1:
self.displayTypeComboBox.insertItem(0, self.automatic)
self.displayTypeComboBox.setCurrentIndex(0)
if QtCore.QSettings().value(self.settingsSection + u'/override player',
QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked:
self.displayTypeComboBox.setCurrentIndex(currentIndex)
if overridePlayer:
self.mediaWidget.show()
else:
self.mediaWidget.hide()
self.displayTypeComboBox.blockSignals(False)
def onDeleteClick(self):
"""

View File

@ -29,7 +29,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate, Receiver
from openlp.core.lib.ui import UiStrings, create_up_down_push_button_set
from openlp.core.ui.media import get_media_players, set_media_players
class MediaQCheckBox(QtGui.QCheckBox):
"""
MediaQCheckBox adds an extra property, playerName to the QCheckBox class.
@ -138,7 +138,7 @@ class MediaTab(SettingsTab):
self.usedPlayers.append(player)
else:
if player in self.usedPlayers:
self.usedPlayers.takeAt(self.usedPlayers.indexOf(player))
self.usedPlayers.remove(player)
self.updatePlayerList()
def updatePlayerList(self):
@ -160,7 +160,7 @@ class MediaTab(SettingsTab):
item = self.playerOrderlistWidget.takeItem(row)
self.playerOrderlistWidget.insertItem(row - 1, item)
self.playerOrderlistWidget.setCurrentRow(row - 1)
self.usedPlayers.move(row, row - 1)
self.usedPlayers.insert(row - 1, self.usedPlayers.pop(row))
def onDownButtonClicked(self):
row = self.playerOrderlistWidget.currentRow()
@ -169,12 +169,12 @@ class MediaTab(SettingsTab):
item = self.playerOrderlistWidget.takeItem(row)
self.playerOrderlistWidget.insertItem(row + 1, item)
self.playerOrderlistWidget.setCurrentRow(row + 1)
self.usedPlayers.move(row, row + 1)
self.usedPlayers.insert(row + 1, self.usedPlayers.pop(row))
def load(self):
self.usedPlayers = QtCore.QSettings().value(
self.settingsSection + u'/players',
QtCore.QVariant(u'webkit')).toString().split(u',')
if self.savedUsedPlayers:
self.usedPlayers = self.savedUsedPlayers
self.usedPlayers = get_media_players()[0]
self.savedUsedPlayers = self.usedPlayers
for key in self.mediaPlayers:
player = self.mediaPlayers[key]
@ -191,18 +191,14 @@ class MediaTab(SettingsTab):
def save(self):
override_changed = False
player_string_changed = False
old_players = QtCore.QSettings().value(
self.settingsSection + u'/players',
QtCore.QVariant(u'webkit')).toString()
new_players = self.usedPlayers.join(u',')
if old_players != new_players:
old_players, override_player = get_media_players()
if self.usedPlayers != old_players:
# clean old Media stuff
QtCore.QSettings().setValue(self.settingsSection + u'/players',
QtCore.QVariant(new_players))
set_media_players(self.usedPlayers, override_player)
player_string_changed = True
override_changed = True
setting_key = self.settingsSection + u'/override player'
if QtCore.QSettings().value(setting_key) != \
if QtCore.QSettings().value(setting_key).toInt()[0] != \
self.overridePlayerCheckBox.checkState():
QtCore.QSettings().setValue(setting_key,
QtCore.QVariant(self.overridePlayerCheckBox.checkState()))

View File

@ -72,7 +72,9 @@ window.OpenLP = {
);
},
loadController: function (event) {
event.preventDefault();
if (event) {
event.preventDefault();
}
$.getJSON(
"/api/controller/live/text",
function (data, status) {
@ -91,6 +93,7 @@ window.OpenLP = {
li.children("a").click(OpenLP.setSlide);
ul.append(li);
}
OpenLP.currentItem = data.results.item;
ul.listview("refresh");
}
);
@ -208,9 +211,8 @@ window.OpenLP = {
},
showAlert: function (event) {
event.preventDefault();
var text = "{\"request\": {\"text\": \"" +
$("#alert-text").val().replace(/\\/g, "\\\\").replace(/"/g, "\\\"") +
"\"}}";
var alert = OpenLP.escapeString($("#alert-text").val())
var text = "{\"request\": {\"text\": \"" + alert + "\"}}";
$.getJSON(
"/api/alert",
{"data": text},
@ -221,9 +223,8 @@ window.OpenLP = {
},
search: function (event) {
event.preventDefault();
var text = "{\"request\": {\"text\": \"" +
$("#search-text").val().replace(/\\/g, "\\\\").replace(/"/g, "\\\"") +
"\"}}";
var query = OpenLP.escapeString($("#search-text").val())
var text = "{\"request\": {\"text\": \"" + query + "\"}}";
$.getJSON(
"/api/" + $("#search-plugin").val() + "/search",
{"data": text},
@ -280,6 +281,9 @@ window.OpenLP = {
);
$("#options").dialog("close");
$.mobile.changePage("#service-manager");
},
escapeString: function (string) {
return string.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")
}
}
// Service Manager

View File

@ -111,15 +111,12 @@ the remotes.
{"results": {"items": [{...}, {...}]}}
"""
import json
import logging
import os
import urlparse
import re
try:
import json
except ImportError:
import simplejson as json
import urllib
import urlparse
from PyQt4 import QtCore, QtNetwork
from mako.template import Template
@ -314,11 +311,14 @@ class HttpConnection(object):
"""
log.debug(u'ready to read socket')
if self.socket.canReadLine():
data = self.socket.readLine()
data = QtCore.QByteArray.fromPercentEncoding(data)
data = unicode(data, 'utf8')
log.debug(u'received: ' + data)
words = data.split(u' ')
data = str(self.socket.readLine())
try:
log.debug(u'received: ' + data)
except UnicodeDecodeError:
# Malicious request containing non-ASCII characters.
self.close()
return
words = data.split(' ')
response = None
if words[0] == u'GET':
url = urlparse.urlparse(words[1])
@ -426,11 +426,19 @@ class HttpConnection(object):
"""
Send an alert.
"""
text = json.loads(self.url_params[u'data'][0])[u'request'][u'text']
plugin = self.parent.plugin.pluginManager.get_plugin_by_name("alerts")
if plugin.status == PluginStatus.Active:
try:
text = json.loads(
self.url_params[u'data'][0])[u'request'][u'text']
except KeyError, ValueError:
return HttpResponse(code=u'400 Bad Request')
text = urllib.unquote(text)
Receiver.send_message(u'alerts_text', [text])
return HttpResponse(json.dumps({u'results': {u'success': True}}),
success = True
else:
success = False
return HttpResponse(json.dumps({u'results': {u'success': success}}),
{u'Content-Type': u'application/json'})
def controller(self, type, action):
@ -465,9 +473,14 @@ class HttpConnection(object):
item[u'selected'] = (self.parent.current_slide == index)
data.append(item)
json_data = {u'results': {u'slides': data}}
if current_item:
json_data[u'results'][u'item'] = self.parent.current_item._uuid
else:
if self.url_params and self.url_params.get(u'data'):
data = json.loads(self.url_params[u'data'][0])
try:
data = json.loads(self.url_params[u'data'][0])
except KeyError, ValueError:
return HttpResponse(code=u'400 Bad Request')
log.info(data)
# This slot expects an int within a list.
id = data[u'request'][u'id']
@ -487,7 +500,10 @@ class HttpConnection(object):
else:
event += u'_item'
if self.url_params and self.url_params.get(u'data'):
data = json.loads(self.url_params[u'data'][0])
try:
data = json.loads(self.url_params[u'data'][0])
except KeyError, ValueError:
return HttpResponse(code=u'400 Bad Request')
Receiver.send_message(event, data[u'request'][u'id'])
else:
Receiver.send_message(event)
@ -520,7 +536,11 @@ class HttpConnection(object):
``type``
The plugin name to search in.
"""
text = json.loads(self.url_params[u'data'][0])[u'request'][u'text']
try:
text = json.loads(self.url_params[u'data'][0])[u'request'][u'text']
except KeyError, ValueError:
return HttpResponse(code=u'400 Bad Request')
text = urllib.unquote(text)
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
if plugin.status == PluginStatus.Active and \
plugin.mediaItem and plugin.mediaItem.hasSearch:
@ -535,20 +555,28 @@ class HttpConnection(object):
"""
Go live on an item of type ``type``.
"""
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
try:
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
except KeyError, ValueError:
return HttpResponse(code=u'400 Bad Request')
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
if plugin.status == PluginStatus.Active and plugin.mediaItem:
plugin.mediaItem.goLive(id, remote=True)
return HttpResponse(code=u'200 OK')
def add_to_service(self, type):
"""
Add item of type ``type`` to the end of the service.
"""
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
try:
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
except KeyError, ValueError:
return HttpResponse(code=u'400 Bad Request')
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
if plugin.status == PluginStatus.Active and plugin.mediaItem:
item_id = plugin.mediaItem.createItemFromId(id)
plugin.mediaItem.addToService(item_id, remote=True)
return HttpResponse(code=u'200 OK')
def send_response(self, response):
http = u'HTTP/1.1 %s\r\n' % response.code

View File

@ -87,7 +87,8 @@ class RemoteTab(SettingsTab):
self.qrLayout = QtGui.QVBoxLayout(self.androidAppGroupBox)
self.qrLayout.setObjectName(u'qrLayout')
self.qrCodeLabel = QtGui.QLabel(self.androidAppGroupBox)
self.qrCodeLabel.setPixmap(QtGui.QPixmap(u':/remotes/android_app_qr.png'))
self.qrCodeLabel.setPixmap(QtGui.QPixmap(
u':/remotes/android_app_qr.png'))
self.qrCodeLabel.setAlignment(QtCore.Qt.AlignCenter)
self.qrCodeLabel.setObjectName(u'qrCodeLabel')
self.qrLayout.addWidget(self.qrCodeLabel)

View File

@ -361,7 +361,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def onAuthorAddButtonClicked(self):
item = int(self.authorsComboBox.currentIndex())
text = unicode(self.authorsComboBox.currentText())
text = unicode(self.authorsComboBox.currentText()).strip(u' \r\n\t')
# This if statement is for OS X, which doesn't seem to work well with
# the QCompleter autocompletion class. See bug #812628.
if text in self.authors:
# Index 0 is a blank string, so add 1
item = self.authors.index(text) + 1
if item == 0 and text:
if QtGui.QMessageBox.question(self,
translate('SongsPlugin.EditSongForm', 'Add Author'),
@ -589,7 +594,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
verse_names.append(u'%s%s' % (
VerseType.translated_tag(verse[0]), verse[1:]))
verses_not_used = []
for count, verse in enumerate(verses):
for verse in verses:
if not verse in order:
verses_not_used.append(verse)
self.warningLabel.setVisible(len(verses_not_used) > 0)
@ -680,7 +685,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.verseListWidget.rowCount())
if not result:
return False
item = int(self.songBookComboBox.currentIndex())
text = unicode(self.songBookComboBox.currentText())
if self.songBookComboBox.findText(text, QtCore.Qt.MatchExactly) < 0:
if QtGui.QMessageBox.question(self,

View File

@ -29,6 +29,7 @@ import re
from PyQt4 import QtGui
from openlp.core.lib import translate
from openlp.core.utils import CONTROL_CHARS
from db import Author
from ui import SongStrings
@ -256,6 +257,13 @@ def clean_string(string):
Strips punctuation from the passed string to assist searching
"""
return WHITESPACE.sub(u' ', APOSTROPHE.sub(u'', string)).lower()
def clean_title(title):
"""
Cleans the song title by removing Unicode control chars groups C0 & C1,
as well as any trailing spaces
"""
return CONTROL_CHARS.sub(u'', title).rstrip()
def clean_song(manager, song):
"""
@ -275,10 +283,14 @@ def clean_song(manager, song):
song.alternate_title = unicode(song.alternate_title)
if isinstance(song.lyrics, buffer):
song.lyrics = unicode(song.lyrics)
song.title = song.title.rstrip() if song.title else u''
if song.alternate_title is None:
if song.title:
song.title = clean_title(song.title)
else:
song.title = u''
if song.alternate_title:
song.alternate_title = clean_title(song.alternate_title)
else:
song.alternate_title = u''
song.alternate_title = song.alternate_title.strip()
song.search_title = clean_string(song.title) + u'@' + \
clean_string(song.alternate_title)
# Only do this, if we the song is a 1.9.4 song (or older).

View File

@ -36,7 +36,7 @@ from sqlalchemy.sql import or_
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
translate, check_item_selected, PluginStatus, create_separated_list
from openlp.core.lib.ui import UiStrings, create_action, create_widget_action
from openlp.core.lib.ui import UiStrings, create_widget_action
from openlp.core.utils import AppLocation
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
SongImportForm, SongExportForm

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

6878
resources/i18n/da.ts Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

6797
resources/i18n/fi.ts Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

6801
resources/i18n/it.ts Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

6799
resources/i18n/pl.ts Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -185,11 +185,11 @@ def download_translations():
**Note:** URLs and headers need to remain strings, not unicode.
"""
global username, password
if not username:
username = raw_input(u'Transifex username: ')
if not password:
password = getpass(u'Transifex password: ')
print_quiet(u'Download translation files from Transifex')
if not username:
username = raw_input(u' Transifex username: ')
if not password:
password = getpass(u' Transifex password: ')
# First get the list of languages
url = SERVER_URL + 'resource/ents/'
base64string = base64.encodestring(