Head 1683

This commit is contained in:
Jon Tibble 2011-07-11 19:35:20 +01:00
commit a5dedf5b8e
13 changed files with 380 additions and 68 deletions

View File

@ -112,17 +112,29 @@ class PriorityQueue(Queue.PriorityQueue):
""" """
Customised ``Queue.PriorityQueue``. Customised ``Queue.PriorityQueue``.
""" """
def remove(self, item): def modify_priority(self, image, new_priority):
""" """
Removes the given ``item`` from the queue. Modifies the priority of the given ``image``.
``item`` ``image``
The item to remove. This should be a tuple:: The image to remove. This should be an ``Image`` instance.
``(Priority, Image)`` ``new_priority``
The image's new priority.
""" """
if item in self.queue: self.remove(image)
self.queue.remove(item) image.priority = new_priority
self.put((image.priority, image))
def remove(self, image):
"""
Removes the given ``image`` from the queue.
``image``
The image to remove. This should be an ``Image`` instance.
"""
if (image.priority, image) in self.queue:
self.queue.remove((image.priority, image))
class ImageManager(QtCore.QObject): class ImageManager(QtCore.QObject):
@ -168,12 +180,16 @@ class ImageManager(QtCore.QObject):
log.debug(u'get_image %s' % name) log.debug(u'get_image %s' % name)
image = self._cache[name] image = self._cache[name]
if image.image is None: if image.image is None:
self._conversion_queue.remove((image.priority, image)) self._conversion_queue.modify_priority(image, Priority.High)
image.priority = Priority.High
self._conversion_queue.put((image.priority, image))
while image.image is None: while image.image is None:
log.debug(u'get_image - waiting') log.debug(u'get_image - waiting')
time.sleep(0.1) time.sleep(0.1)
elif image.image_bytes is None:
# Set the priority to Low, because the image was requested but the
# byte stream was not generated yet. However, we only need to do
# this, when the image was generated before it was requested
# (otherwise this is already taken care of).
self._conversion_queue.modify_priority(image, Priority.Low)
return image.image return image.image
def get_image_bytes(self, name): def get_image_bytes(self, name):
@ -184,9 +200,7 @@ class ImageManager(QtCore.QObject):
log.debug(u'get_image_bytes %s' % name) log.debug(u'get_image_bytes %s' % name)
image = self._cache[name] image = self._cache[name]
if image.image_bytes is None: if image.image_bytes is None:
self._conversion_queue.remove((image.priority, image)) self._conversion_queue.modify_priority(image, Priority.Urgent)
image.priority = Priority.Urgent
self._conversion_queue.put((image.priority, image))
while image.image_bytes is None: while image.image_bytes is None:
log.debug(u'get_image_bytes - waiting') log.debug(u'get_image_bytes - waiting')
time.sleep(0.1) time.sleep(0.1)
@ -198,8 +212,7 @@ class ImageManager(QtCore.QObject):
""" """
log.debug(u'del_image %s' % name) log.debug(u'del_image %s' % name)
if name in self._cache: if name in self._cache:
self._conversion_queue.remove( self._conversion_queue.remove(self._cache[name])
(self._cache[name].priority, self._cache[name]))
del self._cache[name] del self._cache[name]
def add_image(self, name, path): def add_image(self, name, path):
@ -238,18 +251,14 @@ class ImageManager(QtCore.QObject):
# Set the priority to Lowest and stop here as we need to process # Set the priority to Lowest and stop here as we need to process
# more important images first. # more important images first.
if image.priority == Priority.Normal: if image.priority == Priority.Normal:
self._conversion_queue.remove((image.priority, image)) self._conversion_queue.modify_priority(image, Priority.Lowest)
image.priority = Priority.Lowest
self._conversion_queue.put((image.priority, image))
return return
# For image with high priority we set the priority to Low, as the # For image with high priority we set the priority to Low, as the
# byte stream might be needed earlier the byte stream of image with # byte stream might be needed earlier the byte stream of image with
# Normal priority. We stop here as we need to process more important # Normal priority. We stop here as we need to process more important
# images first. # images first.
elif image.priority == Priority.High: elif image.priority == Priority.High:
self._conversion_queue.remove((image.priority, image)) self._conversion_queue.modify_priority(image, Priority.Low)
image.priority = Priority.Low
self._conversion_queue.put((image.priority, image))
return return
# Generate the byte stream for the image. # Generate the byte stream for the image.
if image.image_bytes is None: if image.image_bytes is None:

View File

@ -35,7 +35,7 @@ import logging
import os import os
import uuid import uuid
from openlp.core.lib import build_icon, clean_tags, expand_tags from openlp.core.lib import build_icon, clean_tags, expand_tags, translate
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -352,6 +352,9 @@ class ServiceItem(object):
Updates the _uuid with the value from the original one Updates the _uuid with the value from the original one
The _uuid is unique for a given service item but this allows one to The _uuid is unique for a given service item but this allows one to
replace an original version. replace an original version.
``other``
The service item to be merged with
""" """
self._uuid = other._uuid self._uuid = other._uuid
self.notes = other.notes self.notes = other.notes
@ -447,10 +450,12 @@ class ServiceItem(object):
start = None start = None
end = None end = None
if self.start_time != 0: if self.start_time != 0:
start = UiStrings().StartTimeCode % \ start = unicode(translate('OpenLP.ServiceItem',
'<strong>Start</strong>: %s')) % \
unicode(datetime.timedelta(seconds=self.start_time)) unicode(datetime.timedelta(seconds=self.start_time))
if self.media_length != 0: if self.media_length != 0:
end = UiStrings().LengthTime % \ end = unicode(translate('OpenLP.ServiceItem',
'<strong>Length</strong>: %s')) % \
unicode(datetime.timedelta(seconds=self.media_length)) unicode(datetime.timedelta(seconds=self.media_length))
if not start and not end: if not start and not end:
return None return None
@ -459,5 +464,16 @@ class ServiceItem(object):
elif not start and end: elif not start and end:
return end return end
else: else:
return u'%s : %s' % (start, end) return u'%s <br />%s' % (start, end)
def update_theme(self, theme):
"""
updates the theme in the service item
``theme``
The new theme to be replaced in the service item
"""
self.theme = theme
self._new_item()
self.render()

View File

@ -83,7 +83,6 @@ class UiStrings(object):
self.Image = translate('OpenLP.Ui', 'Image') self.Image = translate('OpenLP.Ui', 'Image')
self.Import = translate('OpenLP.Ui', 'Import') self.Import = translate('OpenLP.Ui', 'Import')
self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:') self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
self.LengthTime = unicode(translate('OpenLP.Ui', 'Length %s'))
self.Live = translate('OpenLP.Ui', 'Live') self.Live = translate('OpenLP.Ui', 'Live')
self.LiveBGError = translate('OpenLP.Ui', 'Live Background Error') self.LiveBGError = translate('OpenLP.Ui', 'Live Background Error')
self.LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar') self.LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar')
@ -103,6 +102,8 @@ class UiStrings(object):
self.OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. ' self.OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. '
'Do you wish to continue?') 'Do you wish to continue?')
self.OpenService = translate('OpenLP.Ui', 'Open service.') self.OpenService = translate('OpenLP.Ui', 'Open service.')
self.PlaySlidesInLoop = translate('OpenLP.Ui','Play Slides in Loop')
self.PlaySlidesToEnd = translate('OpenLP.Ui','Play Slides to End')
self.Preview = translate('OpenLP.Ui', 'Preview') self.Preview = translate('OpenLP.Ui', 'Preview')
self.PrintService = translate('OpenLP.Ui', 'Print Service') self.PrintService = translate('OpenLP.Ui', 'Print Service')
self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background') self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
@ -124,6 +125,10 @@ class UiStrings(object):
self.SplitToolTip = translate('OpenLP.Ui', 'Split a slide into two ' self.SplitToolTip = translate('OpenLP.Ui', 'Split a slide into two '
'only if it does not fit on the screen as one slide.') 'only if it does not fit on the screen as one slide.')
self.StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s')) self.StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s'))
self.StopPlaySlidesInLoop = translate('OpenLP.Ui',
'Stop Play Slides in Loop')
self.StopPlaySlidesToEnd = translate('OpenLP.Ui',
'Stop Play Slides to End')
self.Theme = translate('OpenLP.Ui', 'Theme', 'Singular') self.Theme = translate('OpenLP.Ui', 'Theme', 'Singular')
self.Themes = translate('OpenLP.Ui', 'Themes', 'Plural') self.Themes = translate('OpenLP.Ui', 'Themes', 'Plural')
self.Tools = translate('OpenLP.Ui', 'Tools') self.Tools = translate('OpenLP.Ui', 'Tools')

View File

@ -956,7 +956,19 @@ class ServiceManager(QtGui.QWidget):
treewidgetitem.setIcon(0, treewidgetitem.setIcon(0,
build_icon(u':/general/general_delete.png')) build_icon(u':/general/general_delete.png'))
treewidgetitem.setText(0, serviceitem.get_display_title()) treewidgetitem.setText(0, serviceitem.get_display_title())
treewidgetitem.setToolTip(0, serviceitem.notes) tips = []
if serviceitem.theme and serviceitem.theme != -1:
tips.append(u'<strong>%s:</strong> <em>%s</em>' %
(unicode(translate('OpenLP.ServiceManager', 'Slide theme')),
serviceitem.theme))
if serviceitem.notes:
tips.append(u'<strong>%s: </strong> %s' %
(unicode(translate('OpenLP.ServiceManager', 'Notes')),
unicode(serviceitem.notes)))
if item[u'service_item'] \
.is_capable(ItemCapabilities.AllowsVariableStartTime):
tips.append(item[u'service_item'].get_media_time())
treewidgetitem.setToolTip(0, u'<br />'.join(tips))
treewidgetitem.setData(0, QtCore.Qt.UserRole, treewidgetitem.setData(0, QtCore.Qt.UserRole,
QtCore.QVariant(item[u'order'])) QtCore.QVariant(item[u'order']))
treewidgetitem.setSelected(item[u'selected']) treewidgetitem.setSelected(item[u'selected'])
@ -966,11 +978,6 @@ class ServiceManager(QtGui.QWidget):
text = frame[u'title'].replace(u'\n', u' ') text = frame[u'title'].replace(u'\n', u' ')
child.setText(0, text[:40]) child.setText(0, text[:40])
child.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(count)) child.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(count))
if item[u'service_item'] \
.is_capable(ItemCapabilities.AllowsVariableStartTime):
tip = item[u'service_item'].get_media_time()
if tip:
child.setToolTip(0, tip)
if serviceItem == itemcount: if serviceItem == itemcount:
if item[u'expanded'] and serviceItemChild == count: if item[u'expanded'] and serviceItemChild == count:
self.serviceManagerList.setCurrentItem(child) self.serviceManagerList.setCurrentItem(child)
@ -1338,7 +1345,7 @@ class ServiceManager(QtGui.QWidget):
if not theme: if not theme:
theme = None theme = None
item = self.findServiceItem()[0] item = self.findServiceItem()[0]
self.serviceItems[item][u'service_item'].theme = theme self.serviceItems[item][u'service_item'].update_theme(theme)
self.regenerateServiceItems() self.regenerateServiceItems()
def _getParentItemData(self, item): def _getParentItemData(self, item):

View File

@ -28,12 +28,13 @@
import logging import logging
import os import os
import time import time
import copy
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon from PyQt4.phonon import Phonon
from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \ from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \
translate translate, build_icon
from openlp.core.lib.ui import UiStrings, shortcut_action from openlp.core.lib.ui import UiStrings, shortcut_action
from openlp.core.ui import HideMode, MainDisplay, ScreenList from openlp.core.ui import HideMode, MainDisplay, ScreenList
from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.utils.actions import ActionList, CategoryOrder
@ -194,13 +195,11 @@ class SlideController(QtGui.QWidget):
self.playSlidesLoop = shortcut_action(self.playSlidesMenu, self.playSlidesLoop = shortcut_action(self.playSlidesMenu,
u'playSlidesLoop', [], self.onPlaySlidesLoop, u'playSlidesLoop', [], self.onPlaySlidesLoop,
u':/media/media_time.png', False, UiStrings().LiveToolbar) u':/media/media_time.png', False, UiStrings().LiveToolbar)
self.playSlidesLoop.setText( self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop)
translate('OpenLP.SlideController', 'Play Slides in Loop'))
self.playSlidesOnce = shortcut_action(self.playSlidesMenu, self.playSlidesOnce = shortcut_action(self.playSlidesMenu,
u'playSlidesOnce', [], self.onPlaySlidesOnce, u'playSlidesOnce', [], self.onPlaySlidesOnce,
u':/media/media_time.png', False, UiStrings().LiveToolbar) u':/media/media_time.png', False, UiStrings().LiveToolbar)
self.playSlidesOnce.setText( self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
translate('OpenLP.SlideController', 'Play Slides to End'))
if QtCore.QSettings().value(self.parent().generalSettingsSection + if QtCore.QSettings().value(self.parent().generalSettingsSection +
u'/enable slide loop', QtCore.QVariant(True)).toBool(): u'/enable slide loop', QtCore.QVariant(True)).toBool():
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop) self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
@ -600,7 +599,8 @@ class SlideController(QtGui.QWidget):
log.debug(u'processManagerItem live = %s' % self.isLive) log.debug(u'processManagerItem live = %s' % self.isLive)
self.onStopLoop() self.onStopLoop()
old_item = self.serviceItem old_item = self.serviceItem
self.serviceItem = serviceItem # take a copy not a link to the servicemeanager copy.
self.serviceItem = copy.copy(serviceItem)
if old_item and self.isLive and old_item.is_capable( if old_item and self.isLive and old_item.is_capable(
ItemCapabilities.ProvidesOwnDisplay): ItemCapabilities.ProvidesOwnDisplay):
self._resetBlank() self._resetBlank()
@ -1059,6 +1059,14 @@ class SlideController(QtGui.QWidget):
else: else:
self.playSlidesLoop.setChecked(checked) self.playSlidesLoop.setChecked(checked)
log.debug(u'onPlaySlidesLoop %s' % checked) log.debug(u'onPlaySlidesLoop %s' % checked)
if checked:
self.playSlidesLoop.setIcon(build_icon(u':/media/media_stop.png'))
self.playSlidesLoop.setText(UiStrings().StopPlaySlidesInLoop)
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time.png'))
self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
else:
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop)
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop) self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
self.playSlidesOnce.setChecked(False) self.playSlidesOnce.setChecked(False)
self.onToggleLoop() self.onToggleLoop()
@ -1072,6 +1080,14 @@ class SlideController(QtGui.QWidget):
else: else:
self.playSlidesOnce.setChecked(checked) self.playSlidesOnce.setChecked(checked)
log.debug(u'onPlaySlidesOnce %s' % checked) log.debug(u'onPlaySlidesOnce %s' % checked)
if checked:
self.playSlidesOnce.setIcon(build_icon(u':/media/media_stop.png'))
self.playSlidesOnce.setText(UiStrings().StopPlaySlidesToEnd)
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop)
else:
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time'))
self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
self.playSlidesMenu.setDefaultAction(self.playSlidesOnce) self.playSlidesMenu.setDefaultAction(self.playSlidesOnce)
self.playSlidesLoop.setChecked(False) self.playSlidesLoop.setChecked(False)
self.onToggleLoop() self.onToggleLoop()

View File

@ -145,7 +145,10 @@ class BGExtract(object):
send_error_message(u'download') send_error_message(u'download')
return None return None
page_source = page.read() page_source = page.read()
page_source = unicode(page_source, 'utf8') try:
page_source = unicode(page_source, u'utf8')
except UnicodeDecodeError:
page_source = unicode(page_source, u'cp1251')
page_source_temp = re.search(u'<table .*?class="infotable".*?>.*?'\ page_source_temp = re.search(u'<table .*?class="infotable".*?>.*?'\
u'</table>', page_source, re.DOTALL) u'</table>', page_source, re.DOTALL)
if page_source_temp: if page_source_temp:

View File

@ -267,6 +267,12 @@ def clean_song(manager, song):
``song`` ``song``
The song object. The song object.
""" """
if isinstance(song.title, buffer):
song.title = unicode(song.title)
if isinstance(song.alternate_title, buffer):
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'' song.title = song.title.rstrip() if song.title else u''
if song.alternate_title is None: if song.alternate_title is None:
song.alternate_title = u'' song.alternate_title = u''

View File

@ -48,8 +48,10 @@ class SongUsagePlugin(Plugin):
Plugin.__init__(self, u'SongUsage', plugin_helpers) Plugin.__init__(self, u'SongUsage', plugin_helpers)
self.weight = -4 self.weight = -4
self.icon = build_icon(u':/plugins/plugin_songusage.png') self.icon = build_icon(u':/plugins/plugin_songusage.png')
self.activeIcon = build_icon(u':/songusage/song_usage_active.png')
self.inactiveIcon = build_icon(u':/songusage/song_usage_inactive.png')
self.manager = None self.manager = None
self.songusageActive = False self.songUsageActive = False
def addToolsMenuItem(self, tools_menu): def addToolsMenuItem(self, tools_menu):
""" """
@ -84,17 +86,29 @@ class SongUsagePlugin(Plugin):
self.songUsageStatus.setText(translate( self.songUsageStatus.setText(translate(
'SongUsagePlugin', 'Toggle Tracking')) 'SongUsagePlugin', 'Toggle Tracking'))
self.songUsageStatus.setStatusTip(translate('SongUsagePlugin', self.songUsageStatus.setStatusTip(translate('SongUsagePlugin',
'Toggle the tracking of song usage.')) 'Toggle the tracking of song usage.'))
#Add Menus together # Add Menus together
self.toolsMenu.addAction(self.songUsageMenu.menuAction()) self.toolsMenu.addAction(self.songUsageMenu.menuAction())
self.songUsageMenu.addAction(self.songUsageStatus) self.songUsageMenu.addAction(self.songUsageStatus)
self.songUsageMenu.addSeparator() self.songUsageMenu.addSeparator()
self.songUsageMenu.addAction(self.songUsageDelete) self.songUsageMenu.addAction(self.songUsageDelete)
self.songUsageMenu.addAction(self.songUsageReport) self.songUsageMenu.addAction(self.songUsageReport)
self.songUsageActiveButton = QtGui.QToolButton(
self.formparent.statusBar)
self.songUsageActiveButton.setCheckable(True)
self.songUsageActiveButton.setStatusTip(translate('SongUsagePlugin',
'Toggle the tracking of song usage.'))
self.songUsageActiveButton.setObjectName(u'songUsageActiveButton')
self.formparent.statusBar.insertPermanentWidget(1,
self.songUsageActiveButton)
self.songUsageActiveButton.hide()
# Signals and slots # Signals and slots
QtCore.QObject.connect(self.songUsageStatus, QtCore.QObject.connect(self.songUsageStatus,
QtCore.SIGNAL(u'visibilityChanged(bool)'), QtCore.SIGNAL(u'visibilityChanged(bool)'),
self.songUsageStatus.setChecked) self.songUsageStatus.setChecked)
QtCore.QObject.connect(self.songUsageActiveButton,
QtCore.SIGNAL(u'toggled(bool)'),
self.toggleSongUsageState)
QtCore.QObject.connect(self.songUsageDelete, QtCore.QObject.connect(self.songUsageDelete,
QtCore.SIGNAL(u'triggered()'), self.onSongUsageDelete) QtCore.SIGNAL(u'triggered()'), self.onSongUsageDelete)
QtCore.QObject.connect(self.songUsageReport, QtCore.QObject.connect(self.songUsageReport,
@ -107,23 +121,25 @@ class SongUsagePlugin(Plugin):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_live_started'), QtCore.SIGNAL(u'slidecontroller_live_started'),
self.onReceiveSongUsage) self.onReceiveSongUsage)
self.SongUsageActive = QtCore.QSettings().value( self.songUsageActive = QtCore.QSettings().value(
self.settingsSection + u'/active', self.settingsSection + u'/active',
QtCore.QVariant(False)).toBool() QtCore.QVariant(False)).toBool()
self.songUsageStatus.setChecked(self.SongUsageActive) # Set the button and checkbox state
self.setButtonState()
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_action(self.songUsageStatus,
translate('SongUsagePlugin', 'Song Usage'))
action_list.add_action(self.songUsageDelete, action_list.add_action(self.songUsageDelete,
translate('SongUsagePlugin', 'Song Usage')) translate('SongUsagePlugin', 'Song Usage'))
action_list.add_action(self.songUsageReport, action_list.add_action(self.songUsageReport,
translate('SongUsagePlugin', 'Song Usage')) translate('SongUsagePlugin', 'Song Usage'))
action_list.add_action(self.songUsageStatus,
translate('SongUsagePlugin', 'Song Usage'))
if self.manager is None: if self.manager is None:
self.manager = Manager(u'songusage', init_schema) self.manager = Manager(u'songusage', init_schema)
self.songUsageDeleteForm = SongUsageDeleteForm(self.manager, self.songUsageDeleteForm = SongUsageDeleteForm(self.manager,
self.formparent) self.formparent)
self.songUsageDetailForm = SongUsageDetailForm(self, self.formparent) self.songUsageDetailForm = SongUsageDetailForm(self, self.formparent)
self.songUsageMenu.menuAction().setVisible(True) self.songUsageMenu.menuAction().setVisible(True)
self.songUsageActiveButton.show()
def finalise(self): def finalise(self):
""" """
@ -134,26 +150,55 @@ class SongUsagePlugin(Plugin):
Plugin.finalise(self) Plugin.finalise(self)
self.songUsageMenu.menuAction().setVisible(False) self.songUsageMenu.menuAction().setVisible(False)
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.remove_action(self.songUsageStatus,
translate('SongUsagePlugin', 'Song Usage'))
action_list.remove_action(self.songUsageDelete, action_list.remove_action(self.songUsageDelete,
translate('SongUsagePlugin', 'Song Usage')) translate('SongUsagePlugin', 'Song Usage'))
action_list.remove_action(self.songUsageReport, action_list.remove_action(self.songUsageReport,
translate('SongUsagePlugin', 'Song Usage')) translate('SongUsagePlugin', 'Song Usage'))
action_list.remove_action(self.songUsageStatus, self.songUsageActiveButton.hide()
translate('SongUsagePlugin', 'Song Usage')) # stop any events being processed
#stop any events being processed self.songUsageActive = False
self.SongUsageActive = False
def toggleSongUsageState(self): def toggleSongUsageState(self):
self.SongUsageActive = not self.SongUsageActive """
Manage the state of the audit collection and amend
the UI when necessary,
"""
self.songUsageActive = not self.songUsageActive
QtCore.QSettings().setValue(self.settingsSection + u'/active', QtCore.QSettings().setValue(self.settingsSection + u'/active',
QtCore.QVariant(self.SongUsageActive)) QtCore.QVariant(self.songUsageActive))
self.setButtonState()
def setButtonState(self):
"""
Keep buttons inline. Turn of signals to stop dead loop but we need the
button and check box set correctly.
"""
self.songUsageActiveButton.blockSignals(True)
self.songUsageStatus.blockSignals(True)
if self.songUsageActive:
self.songUsageActiveButton.setIcon(self.activeIcon)
self.songUsageStatus.setChecked(True)
self.songUsageActiveButton.setChecked(True)
self.songUsageActiveButton.setToolTip(translate('SongUsagePlugin',
'Song usage tracking is active.'))
else:
self.songUsageActiveButton.setIcon(self.inactiveIcon)
self.songUsageStatus.setChecked(False)
self.songUsageActiveButton.setChecked(False)
self.songUsageActiveButton.setToolTip(translate('SongUsagePlugin',
'Song usage tracking is inactive.'))
self.songUsageActiveButton.blockSignals(False)
self.songUsageStatus.blockSignals(False)
def onReceiveSongUsage(self, item): def onReceiveSongUsage(self, item):
""" """
Song Usage for live song from SlideController Song Usage for live song from SlideController
""" """
audit = item[0].audit audit = item[0].audit
if self.SongUsageActive and audit: if self.songUsageActive and audit:
song_usage_item = SongUsageItem() song_usage_item = SongUsageItem()
song_usage_item.usagedate = datetime.today() song_usage_item.usagedate = datetime.today()
song_usage_item.usagetime = datetime.now().time() song_usage_item.usagetime = datetime.now().time()

View File

@ -138,6 +138,10 @@
<file>messagebox_info.png</file> <file>messagebox_info.png</file>
<file>messagebox_warning.png</file> <file>messagebox_warning.png</file>
</qresource> </qresource>
<qresource prefix="songusage">
<file>song_usage_active.png</file>
<file>song_usage_inactive.png</file>
</qresource>
<qresource prefix="tools"> <qresource prefix="tools">
<file>tools_add.png</file> <file>tools_add.png</file>
<file>tools_alert.png</file> <file>tools_alert.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

192
scripts/check_dependencies.py Executable file
View File

@ -0,0 +1,192 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2011 Raoul Snyman #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
This script is used to check dependencies of OpenLP. It checks availability
of required python modules and their version. To verify availability of Python
modules, simply run this script::
@:~$ ./check_dependencies.py
"""
import os
import sys
is_win = sys.platform.startswith('win')
VERS = {
'Python': '2.6',
'PyQt4': '4.6',
'Qt4': '4.6',
'sqlalchemy': '0.5',
# pyenchant 1.6 required on Windows
'enchant': '1.6' if is_win else '1.3'
}
# pywin32
WIN32_MODULES = [
'win32com',
'win32ui',
'pywintypes',
]
MODULES = [
'PyQt4',
'PyQt4.QtCore',
'PyQt4.QtGui',
'PyQt4.QtNetwork',
'PyQt4.QtOpenGL',
'PyQt4.QtSvg',
'PyQt4.QtTest',
'PyQt4.QtWebKit',
'PyQt4.phonon',
'sqlalchemy',
'sqlite3',
'lxml',
'chardet',
'enchant',
'BeautifulSoup',
'mako',
]
OPTIONAL_MODULES = [
('sqlite', ' (SQLite 2 support)'),
('MySQLdb', ' (MySQL support)'),
('psycopg2', ' (PostgreSQL support)'),
]
w = sys.stdout.write
def check_vers(version, required, text):
if type(version) is str:
version = version.split('.')
version = [int(x) for x in version]
if type(required) is str:
required = required.split('.')
required = [int(x) for x in required]
w(' %s >= %s ... ' % (text, '.'.join([str(x) for x in required])))
if version >= required:
w('.'.join([str(x) for x in version]) + os.linesep)
return True
else:
w('FAIL' + os.linesep)
return False
def print_vers_fail(required, text):
print(' %s >= %s ... FAIL' % (text, required))
def verify_python():
if not check_vers(list(sys.version_info), VERS['Python'], text='Python'):
exit(1)
def verify_versions():
print('Verifying version of modules...')
try:
from PyQt4 import QtCore
check_vers(QtCore.PYQT_VERSION_STR, VERS['PyQt4'],
'PyQt4')
check_vers(QtCore.qVersion(), VERS['Qt4'],
'Qt4')
except ImportError:
print_vers_fail(VERS['PyQt4'], 'PyQt4')
print_vers_fail(VERS['Qt4'], 'Qt4')
try:
import sqlalchemy
check_vers(sqlalchemy.__version__, VERS['sqlalchemy'], 'sqlalchemy')
except ImportError:
print_vers_fail(VERS['sqlalchemy'], 'sqlalchemy')
try:
import enchant
check_vers(enchant.__version__, VERS['enchant'], 'enchant')
except ImportError:
print_vers_fail(VERS['enchant'], 'enchant')
def check_module(mod, text='', indent=' '):
space = (30 - len(mod) - len(text)) * ' '
w(indent + '%s%s... ' % (mod, text) + space)
try:
__import__(mod)
w('OK')
except ImportError:
w('FAIL')
w(os.linesep)
def verify_pyenchant():
w('Enchant (spell checker)... ')
try:
import enchant
w(os.linesep)
backends = ', '.join([x.name for x in enchant.Broker().describe()])
print(' available backends: %s' % backends)
langs = ', '.join(enchant.list_languages())
print(' available languages: %s' % langs)
except ImportError:
w('FAIL' + os.linesep)
def verify_pyqt():
w('Qt4 image formats... ')
try:
from PyQt4 import QtGui
read_f = ', '.join([unicode(format).lower() \
for format in QtGui.QImageReader.supportedImageFormats()])
write_f= ', '.join([unicode(format).lower() \
for format in QtGui.QImageWriter.supportedImageFormats()])
w(os.linesep)
print(' read: %s' % read_f)
print(' write: %s' % write_f)
except ImportError:
w('FAIL' + os.linesep)
def main():
verify_python()
print('Checking for modules...')
for m in MODULES:
check_module(m)
print('Checking for optional modules...')
for m in OPTIONAL_MODULES:
check_module(m[0], text=m[1])
if is_win:
print('Checking for Windows specific modules...')
for m in WIN32_MODULES:
check_module(m)
verify_versions()
verify_pyqt()
verify_pyenchant()
if __name__ == u'__main__':
main()

View File

@ -96,7 +96,7 @@ psvince.dll
the install will fail. The dll can be obtained from here: the install will fail. The dll can be obtained from here:
http://www.vincenzo.net/isxkb/index.php?title=PSVince) http://www.vincenzo.net/isxkb/index.php?title=PSVince)
Mako Mako
Mako Templates for Python. This package is required for building the Mako Templates for Python. This package is required for building the
remote plugin. It can be installed by going to your remote plugin. It can be installed by going to your
python_directory\scripts\.. and running "easy_install Mako". If you do not python_directory\scripts\.. and running "easy_install Mako". If you do not
@ -133,7 +133,14 @@ site_packages = os.path.join(os.path.split(python_exe)[0], u'Lib',
pyi_build = os.path.abspath(os.path.join(branch_path, u'..', u'..', pyi_build = os.path.abspath(os.path.join(branch_path, u'..', u'..',
u'pyinstaller', u'pyinstaller.py')) u'pyinstaller', u'pyinstaller.py'))
openlp_main_script = os.path.abspath(os.path.join(branch_path, 'openlp.pyw')) openlp_main_script = os.path.abspath(os.path.join(branch_path, 'openlp.pyw'))
lrelease_exe = os.path.join(site_packages, u'PyQt4', u'bin', u'lrelease.exe') if os.path.exists(os.path.join(site_packages, u'PyQt4', u'bin')):
# Older versions of the PyQt4 Windows installer put their binaries in the
# "bin" directory
lrelease_exe = os.path.join(site_packages, u'PyQt4', u'bin', u'lrelease.exe')
else:
# Newer versions of the PyQt4 Windows installer put their binaries in the
# base directory of the installation
lrelease_exe = os.path.join(site_packages, u'PyQt4', u'lrelease.exe')
i18n_utils = os.path.join(script_path, u'translation_utils.py') i18n_utils = os.path.join(script_path, u'translation_utils.py')
win32_icon = os.path.join(branch_path, u'resources', u'images', 'OpenLP.ico') win32_icon = os.path.join(branch_path, u'resources', u'images', 'OpenLP.ico')
@ -145,7 +152,7 @@ helpfile_path = os.path.join(manual_build_path, u'htmlhelp')
i18n_path = os.path.join(branch_path, u'resources', u'i18n') i18n_path = os.path.join(branch_path, u'resources', u'i18n')
winres_path = os.path.join(branch_path, u'resources', u'windows') winres_path = os.path.join(branch_path, u'resources', u'windows')
build_path = os.path.join(branch_path, u'build') build_path = os.path.join(branch_path, u'build')
dist_path = os.path.join(build_path, u'dist', u'OpenLP') dist_path = os.path.join(branch_path, u'dist', u'OpenLP')
pptviewlib_path = os.path.join(source_path, u'plugins', u'presentations', pptviewlib_path = os.path.join(source_path, u'plugins', u'presentations',
u'lib', u'pptviewlib') u'lib', u'pptviewlib')
@ -172,7 +179,7 @@ def run_pyinstaller():
pyinstaller = Popen((python_exe, pyi_build, pyinstaller = Popen((python_exe, pyi_build,
u'--noconfirm', u'--noconfirm',
u'--windowed', u'--windowed',
u'-o', build_path, u'-o', branch_path,
u'-i', win32_icon, u'-i', win32_icon,
u'-p', branch_path, u'-p', branch_path,
u'-n', 'OpenLP', u'-n', 'OpenLP',
@ -319,17 +326,19 @@ def main():
import sys import sys
for arg in sys.argv: for arg in sys.argv:
if arg == u'-v' or arg == u'--verbose': if arg == u'-v' or arg == u'--verbose':
print "Script path:", script_path print "OpenLP main script: ......", openlp_main_script
print "Branch path:", branch_path print "Script path: .............", script_path
print "Source path:", source_path print "Branch path: .............", branch_path
print "\"dist\" path:", dist_path print "Source path: .............", source_path
print "PyInstaller:", pyi_build print "\"dist\" path: .............", dist_path
print "PyInstaller: .............", pyi_build
print "Documentation branch path:", doc_branch_path print "Documentation branch path:", doc_branch_path
print "Help file build path;", helpfile_path print "Help file build path: ....", helpfile_path
print "Inno Setup path:", innosetup_exe print "Inno Setup path: .........", innosetup_exe
print "Windows resources:", winres_path print "Windows resources: .......", winres_path
print "VCBuild path:", vcbuild_exe print "VCBuild path: ............", vcbuild_exe
print "PPTVIEWLIB path:", pptviewlib_path print "PPTVIEWLIB path: .........", pptviewlib_path
print ""
elif arg == u'--skip-update': elif arg == u'--skip-update':
skip_update = True skip_update = True
elif arg == u'/?' or arg == u'-h' or arg == u'--help': elif arg == u'/?' or arg == u'-h' or arg == u'--help':