diff --git a/copyright.txt b/copyright.txt
index c99a64287..6882a7282 100644
--- a/copyright.txt
+++ b/copyright.txt
@@ -4,8 +4,8 @@
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2010 Raoul Snyman #
-# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Copyright (c) 2008-2011 Raoul Snyman #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, Frode Woldsund #
diff --git a/documentation/api/source/core/lib.rst b/documentation/api/source/core/lib.rst
index 6ca952d7d..fa894875d 100644
--- a/documentation/api/source/core/lib.rst
+++ b/documentation/api/source/core/lib.rst
@@ -6,18 +6,18 @@ Object Library
.. automodule:: openlp.core.lib
:members:
-:mod:`BaseListWithDnD`
-----------------------
-
-.. autoclass:: openlp.core.lib.baselistwithdnd.BaseListWithDnD
- :members:
-
:mod:`EventReceiver`
--------------------
.. autoclass:: openlp.core.lib.eventreceiver.EventReceiver
:members:
+:mod:`ListWidgetWithDnD`
+----------------------
+
+.. autoclass:: openlp.core.lib.listwidgetwithdnd.ListWidgetWithDnD
+ :members:
+
:mod:`MediaManagerItem`
-----------------------
diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py
index 33280f83b..5247ae938 100644
--- a/openlp/core/lib/__init__.py
+++ b/openlp/core/lib/__init__.py
@@ -319,6 +319,7 @@ def check_directory_exists(dir):
if not os.path.exists(dir):
os.makedirs(dir)
+from listwidgetwithdnd import ListWidgetWithDnD
from theme import ThemeLevel, ThemeXML, BackgroundGradientType, \
BackgroundType, HorizontalType, VerticalType
from displaytags import DisplayTags
@@ -339,4 +340,3 @@ from dockwidget import OpenLPDockWidget
from renderer import Renderer
from rendermanager import RenderManager
from mediamanageritem import MediaManagerItem
-from baselistwithdnd import BaseListWithDnD
diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py
index ea830855c..34d583181 100644
--- a/openlp/core/lib/htmlbuilder.py
+++ b/openlp/core/lib/htmlbuilder.py
@@ -28,7 +28,8 @@ import logging
from PyQt4 import QtWebKit
-from openlp.core.lib import BackgroundType, BackgroundGradientType
+from openlp.core.lib import BackgroundType, BackgroundGradientType, \
+ VerticalType
log = logging.getLogger(__name__)
@@ -536,12 +537,7 @@ def build_lyrics_format_css(theme, width, height):
align = u'right'
else:
align = u'left'
- if theme.display_vertical_align == 2:
- valign = u'bottom'
- elif theme.display_vertical_align == 1:
- valign = u'middle'
- else:
- valign = u'top'
+ valign = VerticalType.to_string(theme.display_vertical_align)
if theme.font_main_outline:
left_margin = int(theme.font_main_outline_size) * 2
else:
@@ -634,13 +630,7 @@ def build_alert_css(alertTab, width):
"""
if not alertTab:
return u''
- align = u''
- if alertTab.location == 2:
- align = u'bottom'
- elif alertTab.location == 1:
- align = u'middle'
- else:
- align = u'top'
+ align = VerticalType.to_string(alertTab.location)
alert = style % (width, align, alertTab.font_face, alertTab.font_size,
alertTab.font_color, alertTab.bg_color)
return alert
diff --git a/openlp/core/lib/baselistwithdnd.py b/openlp/core/lib/listwidgetwithdnd.py
similarity index 90%
rename from openlp/core/lib/baselistwithdnd.py
rename to openlp/core/lib/listwidgetwithdnd.py
index 86535f6e7..a1a11217b 100644
--- a/openlp/core/lib/baselistwithdnd.py
+++ b/openlp/core/lib/listwidgetwithdnd.py
@@ -28,17 +28,17 @@ Extend QListWidget to handle drag and drop functionality
"""
from PyQt4 import QtCore, QtGui
-class BaseListWithDnD(QtGui.QListWidget):
+class ListWidgetWithDnD(QtGui.QListWidget):
"""
Provide a list widget to store objects and handle drag and drop events
"""
- def __init__(self, parent=None):
+ def __init__(self, parent=None, name=u''):
"""
Initialise the list widget
"""
QtGui.QListWidget.__init__(self, parent)
- # this must be set by the class which is inheriting
- assert(self.PluginName)
+ self.mimeDataText = name
+ assert(self.mimeDataText)
def mouseMoveEvent(self, event):
"""
@@ -47,9 +47,10 @@ class BaseListWithDnD(QtGui.QListWidget):
just tell it what plugin to call
"""
if event.buttons() != QtCore.Qt.LeftButton:
+ event.ignore()
return
drag = QtGui.QDrag(self)
mimeData = QtCore.QMimeData()
drag.setMimeData(mimeData)
- mimeData.setText(self.PluginName)
- drag.start(QtCore.Qt.CopyAction)
\ No newline at end of file
+ mimeData.setText(self.mimeDataText)
+ drag.start(QtCore.Qt.CopyAction)
diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py
index cc80ad564..f74ba63a9 100644
--- a/openlp/core/lib/mediamanageritem.py
+++ b/openlp/core/lib/mediamanageritem.py
@@ -33,7 +33,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import context_menu_action, context_menu_separator, \
SettingsManager, OpenLPToolbar, ServiceItem, StringContent, build_icon, \
- translate, Receiver
+ translate, Receiver, ListWidgetWithDnD
log = logging.getLogger(__name__)
@@ -73,11 +73,6 @@ class MediaManagerItem(QtGui.QWidget):
assumes that the new action is to load a file. If not, you
need to override the ``OnNew`` method.
- ``self.ListViewWithDnD_class``
- This must be a **class**, not an object, descended from
- ``openlp.core.lib.BaseListWithDnD`` that is not used in any
- other part of OpenLP.
-
``self.PreviewFunction``
This must be a method which returns a QImage to represent the
item (usually a preview). No scaling is required, that is
@@ -202,68 +197,50 @@ class MediaManagerItem(QtGui.QWidget):
"""
Create buttons for the media item toolbar
"""
+ toolbar_actions = []
## Import Button ##
if self.hasImportIcon:
- import_string = self.plugin.getString(StringContent.Import)
- self.addToolbarButton(
- import_string[u'title'],
- import_string[u'tooltip'],
- u':/general/general_import.png', self.onImportClick)
+ toolbar_actions.append([StringContent.Import,
+ u':/general/general_import.png', self.onImportClick])
## Load Button ##
if self.hasFileIcon:
- load_string = self.plugin.getString(StringContent.Load)
- self.addToolbarButton(
- load_string[u'title'],
- load_string[u'tooltip'],
- u':/general/general_open.png', self.onFileClick)
+ toolbar_actions.append([StringContent.Load,
+ u':/general/general_open.png', self.onFileClick])
## New Button ##
if self.hasNewIcon:
- new_string = self.plugin.getString(StringContent.New)
- self.addToolbarButton(
- new_string[u'title'],
- new_string[u'tooltip'],
- u':/general/general_new.png', self.onNewClick)
+ toolbar_actions.append([StringContent.New,
+ u':/general/general_new.png', self.onNewClick])
## Edit Button ##
if self.hasEditIcon:
- edit_string = self.plugin.getString(StringContent.Edit)
- self.addToolbarButton(
- edit_string[u'title'],
- edit_string[u'tooltip'],
- u':/general/general_edit.png', self.onEditClick)
+ toolbar_actions.append([StringContent.Edit,
+ u':/general/general_edit.png', self.onEditClick])
## Delete Button ##
if self.hasDeleteIcon:
- delete_string = self.plugin.getString(StringContent.Delete)
- self.addToolbarButton(
- delete_string[u'title'],
- delete_string[u'tooltip'],
- u':/general/general_delete.png', self.onDeleteClick)
+ toolbar_actions.append([StringContent.Delete,
+ u':/general/general_delete.png', self.onDeleteClick])
## Separator Line ##
self.addToolbarSeparator()
## Preview ##
- preview_string = self.plugin.getString(StringContent.Preview)
- self.addToolbarButton(
- preview_string[u'title'],
- preview_string[u'tooltip'],
- u':/general/general_preview.png', self.onPreviewClick)
+ toolbar_actions.append([StringContent.Preview,
+ u':/general/general_preview.png', self.onPreviewClick])
## Live Button ##
- live_string = self.plugin.getString(StringContent.Live)
- self.addToolbarButton(
- live_string[u'title'],
- live_string[u'tooltip'],
- u':/general/general_live.png', self.onLiveClick)
+ toolbar_actions.append([StringContent.Live,
+ u':/general/general_live.png', self.onLiveClick])
## Add to service Button ##
- service_string = self.plugin.getString(StringContent.Service)
- self.addToolbarButton(
- service_string[u'title'],
- service_string[u'tooltip'],
- u':/general/general_add.png', self.onAddClick)
+ toolbar_actions.append([StringContent.Service,
+ u':/general/general_add.png', self.onAddClick])
+ for action in toolbar_actions:
+ self.addToolbarButton(
+ self.plugin.getString(action[0])[u'title'],
+ self.plugin.getString(action[0])[u'tooltip'],
+ action[1], action[2])
def addListViewToToolBar(self):
"""
Creates the main widget for listing items the media item is tracking
"""
# Add the List widget
- self.listView = self.ListViewWithDnD_class(self)
+ self.listView = ListWidgetWithDnD(self, self.title)
self.listView.uniformItemSizes = True
self.listView.setSpacing(1)
self.listView.setSelectionMode(
@@ -500,7 +477,7 @@ class MediaManagerItem(QtGui.QWidget):
"""
if not self.listView.selectedIndexes() and not self.remoteTriggered:
QtGui.QMessageBox.information(self,
- translate('OpenLP.MediaManagerItem', 'No items selected'),
+ translate('OpenLP.MediaManagerItem', 'No Items Selected'),
translate('OpenLP.MediaManagerItem',
'You must select one or more items'))
else:
diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py
index cfd3fb4c2..730bb1a36 100644
--- a/openlp/core/lib/plugin.py
+++ b/openlp/core/lib/plugin.py
@@ -114,7 +114,8 @@ class Plugin(QtCore.QObject):
"""
log.info(u'loaded')
- def __init__(self, name, version=None, pluginHelpers=None):
+ def __init__(self, name, version=None, pluginHelpers=None,
+ mediaItemClass=None, settingsTabClass=None):
"""
This is the constructor for the plugin object. This provides an easy
way for descendent plugins to populate common data. This method *must*
@@ -132,6 +133,12 @@ class Plugin(QtCore.QObject):
``pluginHelpers``
Defaults to *None*. A list of helper objects.
+
+ ``mediaItemClass``
+ The class name of the plugin's media item.
+
+ ``settingsTabClass``
+ The class name of the plugin's settings tab.
"""
QtCore.QObject.__init__(self)
self.name = name
@@ -141,6 +148,8 @@ class Plugin(QtCore.QObject):
self.version = version
self.settingsSection = self.name.lower()
self.icon = None
+ self.mediaItemClass = mediaItemClass
+ self.settingsTabClass = settingsTabClass
self.weight = 0
self.status = PluginStatus.Inactive
# Set up logging
@@ -199,7 +208,9 @@ class Plugin(QtCore.QObject):
Construct a MediaManagerItem object with all the buttons and things
you need, and return it for integration into openlp.org.
"""
- pass
+ if self.mediaItemClass:
+ return self.mediaItemClass(self, self, self.icon)
+ return None
def addImportMenuItem(self, importMenu):
"""
@@ -230,9 +241,13 @@ class Plugin(QtCore.QObject):
def getSettingsTab(self):
"""
- Create a tab for the settings window.
+ Create a tab for the settings window to display the configurable
+ options for this plugin to the user.
"""
- pass
+ if self.settingsTabClass:
+ return self.settingsTabClass(self.name,
+ self.getString(StringContent.VisibleName)[u'title'])
+ return None
def addToMenu(self, menubar):
"""
@@ -320,37 +335,39 @@ class Plugin(QtCore.QObject):
"""
return self.textStrings[name]
- def setPluginTextStrings(self):
+ def setPluginUiTextStrings(self, tooltips):
"""
Called to define all translatable texts of the plugin
"""
## Load Action ##
- self._setSingularTextString(StringContent.Load,
- UiStrings.Load, UiStrings.LoadANew)
+ self.__setNameTextString(StringContent.Load,
+ UiStrings.Load, tooltips[u'load'])
+ ## Import Action ##
+ self.__setNameTextString(StringContent.Import,
+ UiStrings.Import, tooltips[u'import'])
## New Action ##
- self._setSingularTextString(StringContent.New,
- UiStrings.Add, UiStrings.AddANew)
+ self.__setNameTextString(StringContent.New,
+ UiStrings.Add, tooltips[u'new'])
## Edit Action ##
- self._setSingularTextString(StringContent.Edit,
- UiStrings.Edit, UiStrings.EditSelect)
+ self.__setNameTextString(StringContent.Edit,
+ UiStrings.Edit, tooltips[u'edit'])
## Delete Action ##
- self._setSingularTextString(StringContent.Delete,
- UiStrings.Delete, UiStrings.DeleteSelect)
+ self.__setNameTextString(StringContent.Delete,
+ UiStrings.Delete, tooltips[u'delete'])
## Preview Action ##
- self._setSingularTextString(StringContent.Preview,
- UiStrings.Preview, UiStrings.PreviewSelect)
+ self.__setNameTextString(StringContent.Preview,
+ UiStrings.Preview, tooltips[u'preview'])
## Send Live Action ##
- self._setSingularTextString(StringContent.Live,
- UiStrings.Live, UiStrings.SendSelectLive)
+ self.__setNameTextString(StringContent.Live,
+ UiStrings.Live, tooltips[u'live'])
## Add to Service Action ##
- self._setSingularTextString(StringContent.Service,
- UiStrings.Service, UiStrings.AddSelectService)
+ self.__setNameTextString(StringContent.Service,
+ UiStrings.Service, tooltips[u'service'])
- def _setSingularTextString(self, name, title, tooltip):
+ def __setNameTextString(self, name, title, tooltip):
"""
Utility method for creating a plugin's textStrings. This method makes
use of the singular name of the plugin object so must only be called
after this has been set.
"""
- self.textStrings[name] = { u'title': title, u'tooltip': tooltip %
- self.getString(StringContent.Name)[u'singular']}
+ self.textStrings[name] = {u'title': title, u'tooltip': tooltip}
diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py
index 5896ca4e6..32a29915f 100644
--- a/openlp/core/lib/rendermanager.py
+++ b/openlp/core/lib/rendermanager.py
@@ -68,7 +68,6 @@ class RenderManager(object):
self.theme_level = u''
self.override_background = None
self.theme_data = None
- self.alertTab = None
self.force_page = False
def update_display(self):
@@ -261,4 +260,4 @@ class RenderManager(object):
log.debug(u'calculate default %d, %d, %f',
self.width, self.height, self.screen_ratio )
# 90% is start of footer
- self.footer_start = int(self.height * 0.90)
\ No newline at end of file
+ self.footer_start = int(self.height * 0.90)
diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py
index c74b89144..31852709a 100644
--- a/openlp/core/lib/serviceitem.py
+++ b/openlp/core/lib/serviceitem.py
@@ -28,11 +28,13 @@ The :mod:`serviceitem` provides the service item functionality including the
type and capability of an item.
"""
+import datetime
import logging
import os
import uuid
from openlp.core.lib import build_icon, clean_tags, expand_tags
+from openlp.core.lib.ui import UiStrings
log = logging.getLogger(__name__)
@@ -60,6 +62,7 @@ class ItemCapabilities(object):
AddIfNewItem = 9
ProvidesOwnDisplay = 10
AllowsDetailedTitleDisplay = 11
+ AllowsVarableStartTime = 12
class ServiceItem(object):
@@ -105,6 +108,8 @@ class ServiceItem(object):
self.data_string = u''
self.edit_id = None
self.xml_version = None
+ self.start_time = 0
+ self.media_length = 0
self._new_item()
def _new_item(self):
@@ -257,7 +262,9 @@ class ServiceItem(object):
u'capabilities': self.capabilities,
u'search': self.search_string,
u'data': self.data_string,
- u'xml_version': self.xml_version
+ u'xml_version': self.xml_version,
+ u'start_time': self.start_time,
+ u'media_length': self.media_length
}
service_data = []
if self.service_item_type == ServiceItemType.Text:
@@ -301,6 +308,10 @@ class ServiceItem(object):
self.data_string = header[u'data']
if u'xml_version' in header:
self.xml_version = header[u'xml_version']
+ if u'start_time' in header:
+ self.start_time = header[u'start_time']
+ if u'media_length' in header:
+ self.media_length = header[u'media_length']
if self.service_item_type == ServiceItemType.Text:
for slide in serviceitem[u'serviceitem'][u'data']:
self._raw_frames.append(slide)
@@ -420,3 +431,25 @@ class ServiceItem(object):
return self._raw_frames[row][u'path']
except IndexError:
return u''
+
+ def get_media_time(self):
+ """
+ Returns the start and finish time for a media item
+ """
+ tooltip = None
+ start = None
+ end = None
+ if self.start_time != 0:
+ start = UiStrings.StartTimeCode % \
+ unicode(datetime.timedelta(seconds=self.start_time))
+ if self.media_length != 0:
+ end = UiStrings.LengthTime % \
+ unicode(datetime.timedelta(seconds=self.media_length))
+ if not start and not end:
+ return None
+ elif start and not end:
+ return start
+ elif not start and end:
+ return end
+ else:
+ return u'%s : %s' % (start, end)
diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py
index dca226069..4189452bc 100644
--- a/openlp/core/lib/theme.py
+++ b/openlp/core/lib/theme.py
@@ -164,13 +164,27 @@ class BackgroundGradientType(object):
elif type_string == u'leftBottom':
return BackgroundGradientType.LeftBottom
+
class HorizontalType(object):
"""
Type enumeration for horizontal alignment.
"""
Left = 0
- Center = 1
- Right = 2
+ Center = 2
+ Right = 1
+
+ @staticmethod
+ def to_string(horizontal_type):
+ """
+ Return a string representation of a horizontal type.
+ """
+ if horizontal_type == Horizontal.Right:
+ return u'right'
+ elif horizontal_type == Horizontal.Center:
+ return u'center'
+ else:
+ return u'left'
+
class VerticalType(object):
"""
@@ -180,6 +194,19 @@ class VerticalType(object):
Middle = 1
Bottom = 2
+ @staticmethod
+ def to_string(vertical_type):
+ """
+ Return a string representation of a vertical type.
+ """
+ if vertical_type == VerticalType.Bottom:
+ return u'bottom'
+ elif vertical_type == VerticalType.Middle:
+ return u'middle'
+ else:
+ return u'top'
+
+
BOOLEAN_LIST = [u'bold', u'italics', u'override', u'outline', u'shadow',
u'slide_transition']
diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py
index ec1c324fe..a98e2fb7f 100644
--- a/openlp/core/lib/ui.py
+++ b/openlp/core/lib/ui.py
@@ -41,36 +41,32 @@ class UiStrings(object):
# These strings should need a good reason to be retranslated elsewhere.
# Should some/more/less of these have an & attached?
Add = translate('OpenLP.Ui', '&Add')
- AddANew = unicode(translate('OpenLP.Ui', 'Add a new %s'))
- AddSelectService = unicode(translate('OpenLP.Ui',
- 'Add the selected %s to the service'))
+ Advanced = translate('OpenLP.Ui', 'Advanced')
AllFiles = translate('OpenLP.Ui', 'All Files')
Authors = translate('OpenLP.Ui', 'Authors')
+ CreateService = translate('OpenLP.Ui', 'Create a new service.')
Delete = translate('OpenLP.Ui', '&Delete')
- DeleteSelect = unicode(translate('OpenLP.Ui', 'Delete the selected %s'))
- DeleteType = unicode(translate('OpenLP.Ui', 'Delete %s'))
Edit = translate('OpenLP.Ui', '&Edit')
- EditSelect = unicode(translate('OpenLP.Ui', 'Edit the selected %s'))
- EditType = unicode(translate('OpenLP.Ui', 'Edit %s'))
Error = translate('OpenLP.Ui', 'Error')
- ExportType = unicode(translate('OpenLP.Ui', 'Export %s'))
Import = translate('OpenLP.Ui', 'Import')
- ImportType = unicode(translate('OpenLP.Ui', 'Import %s'))
+ LengthTime = unicode(translate('OpenLP.Ui', 'Length %s'))
Live = translate('OpenLP.Ui', 'Live')
Load = translate('OpenLP.Ui', 'Load')
- LoadANew = unicode(translate('OpenLP.Ui', 'Load a new %s'))
New = translate('OpenLP.Ui', 'New')
- NewType = unicode(translate('OpenLP.Ui', 'New %s'))
+ NewService = translate('OpenLP.Ui', 'New Service')
OLPV2 = translate('OpenLP.Ui', 'OpenLP 2.0')
+ OpenService = translate('OpenLP.Ui', 'Open Service')
Preview = translate('OpenLP.Ui', 'Preview')
- PreviewSelect = unicode(translate('OpenLP.Ui', 'Preview the selected %s'))
- SendSelectLive = unicode(translate('OpenLP.Ui',
- 'Send the selected %s live'))
+ ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
+ ReplaceLiveBG = translate('OpenLP.Ui', 'Replace Live Background')
+ ResetBG = translate('OpenLP.Ui', 'Reset Background')
+ ResetLiveBG = translate('OpenLP.Ui', 'Reset Live Background')
+ SaveService = translate('OpenLP.Ui', 'Save Service')
Service = translate('OpenLP.Ui', 'Service')
+ StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s'))
Theme = translate('OpenLP.Ui', 'Theme')
Themes = translate('OpenLP.Ui', 'Themes')
-
def add_welcome_page(parent, image):
"""
Generate an opening welcome page for a wizard using a provided image.
@@ -98,18 +94,25 @@ def add_welcome_page(parent, image):
parent.welcomeLayout.addStretch()
parent.addPage(parent.welcomePage)
-def create_save_cancel_button_box(parent):
+def create_accept_reject_button_box(parent, okay=False):
"""
- Creates a standard dialog button box with save and cancel buttons. The
- button box is connected to the parent's ``accept()`` and ``reject()``
+ Creates a standard dialog button box with two buttons. The buttons default
+ to save and cancel but the ``okay`` parameter can be used to make the
+ buttons okay and cancel instead.
+ The button box is connected to the parent's ``accept()`` and ``reject()``
methods to handle the default ``accepted()`` and ``rejected()`` signals.
``parent``
The parent object. This should be a ``QWidget`` descendant.
+
+ ``okay``
+ If true creates an okay/cancel combination instead of save/cancel.
"""
button_box = QtGui.QDialogButtonBox(parent)
- button_box.setStandardButtons(
- QtGui.QDialogButtonBox.Save | QtGui.QDialogButtonBox.Cancel)
+ accept_button = QtGui.QDialogButtonBox.Save
+ if okay:
+ accept_button = QtGui.QDialogButtonBox.Ok
+ button_box.setStandardButtons(accept_button | QtGui.QDialogButtonBox.Cancel)
button_box.setObjectName(u'%sButtonBox' % parent)
QtCore.QObject.connect(button_box, QtCore.SIGNAL(u'accepted()'),
parent.accept)
diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py
index eb0e89775..45218802e 100644
--- a/openlp/core/ui/__init__.py
+++ b/openlp/core/ui/__init__.py
@@ -28,7 +28,7 @@ The :mod:`ui` module provides the core user interface for OpenLP
"""
from PyQt4 import QtGui
-from openlp.core.lib import translate, Receiver
+from openlp.core.lib import translate
class HideMode(object):
"""
@@ -53,6 +53,7 @@ class HideMode(object):
from themeform import ThemeForm
from filerenameform import FileRenameForm
+from starttimeform import StartTimeForm
from maindisplay import MainDisplay
from servicenoteform import ServiceNoteForm
from serviceitemeditform import ServiceItemEditForm
diff --git a/openlp/core/ui/aboutdialog.py b/openlp/core/ui/aboutdialog.py
index 597d3fb24..bb09ab91f 100644
--- a/openlp/core/ui/aboutdialog.py
+++ b/openlp/core/ui/aboutdialog.py
@@ -164,9 +164,10 @@ class Ui_AboutDialog(object):
self.licenseTextEdit.setPlainText(translate('OpenLP.AboutForm',
'Copyright \xa9 2004-2011 Raoul Snyman\n'
'Portions copyright \xa9 2004-2011 '
- 'Tim Bentley, Jonathan Corwin, Michael Gorven, Scott Guerrieri, '
- 'Christian Richter, Maikel Stuivenberg, Martin Thompson, Jon '
- 'Tibble, Carsten Tinggaard\n'
+ 'Tim Bentley, Jonathan Corwin, Michael Gorven, Scott Guerrieri,\n'
+ 'Meinert Jordan, Andreas Preikschat, Christian Richter, Philip\n'
+ 'Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, Carstenn'
+ 'Tinggaard, Frode Woldsund\n'
'\n'
'This program is free software; you can redistribute it and/or '
'modify it under the terms of the GNU General Public License as '
diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py
index 58b637bc2..918335b2e 100644
--- a/openlp/core/ui/advancedtab.py
+++ b/openlp/core/ui/advancedtab.py
@@ -29,6 +29,7 @@ The :mod:`advancedtab` provides an advanced settings facility.
from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate
+from openlp.core.lib.ui import UiStrings
class AdvancedTab(SettingsTab):
"""
@@ -112,7 +113,7 @@ class AdvancedTab(SettingsTab):
"""
Setup the interface translation strings.
"""
- self.tabTitleVisible = translate('OpenLP.AdvancedTab', 'Advanced')
+ self.tabTitleVisible = UiStrings.Advanced
self.uiGroupBox.setTitle(translate('OpenLP.AdvancedTab', 'UI Settings'))
self.recentLabel.setText(
translate('OpenLP.AdvancedTab',
diff --git a/openlp/core/ui/exceptionform.py b/openlp/core/ui/exceptionform.py
index 7f9e23c61..f0c1c9ab0 100644
--- a/openlp/core/ui/exceptionform.py
+++ b/openlp/core/ui/exceptionform.py
@@ -56,6 +56,7 @@ except ImportError:
from openlp.core.lib import translate, SettingsManager
from openlp.core.lib.mailto import mailto
+from openlp.core.lib.ui import UiStrings
from exceptiondialog import Ui_ExceptionDialog
@@ -176,8 +177,7 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
self,translate('ImagePlugin.ExceptionDialog',
'Select Attachment'),
SettingsManager.get_last_dir(u'exceptions'),
- u'%s (*.*) (*)' %
- unicode(translate('ImagePlugin.MediaItem', 'All Files')))
+ u'%s (*.*) (*)' % UiStrings.AllFiles)
log.info(u'New files(s) %s', unicode(files))
if files:
self.fileAttachment = unicode(files)
diff --git a/openlp/core/ui/filerenamedialog.py b/openlp/core/ui/filerenamedialog.py
index c9a8a7633..147207494 100644
--- a/openlp/core/ui/filerenamedialog.py
+++ b/openlp/core/ui/filerenamedialog.py
@@ -27,30 +27,28 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
+from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_FileRenameDialog(object):
- def setupUi(self, FileRenameDialog):
- FileRenameDialog.setObjectName(u'FileRenameDialog')
- FileRenameDialog.resize(300, 10)
- self.dialogLayout = QtGui.QGridLayout(FileRenameDialog)
+ def setupUi(self, fileRenameDialog):
+ fileRenameDialog.setObjectName(u'fileRenameDialog')
+ fileRenameDialog.resize(300, 10)
+ self.dialogLayout = QtGui.QGridLayout(fileRenameDialog)
self.dialogLayout.setObjectName(u'dialogLayout')
- self.fileNameLabel = QtGui.QLabel(FileRenameDialog)
+ self.fileNameLabel = QtGui.QLabel(fileRenameDialog)
self.fileNameLabel.setObjectName(u'fileNameLabel')
self.dialogLayout.addWidget(self.fileNameLabel, 0, 0)
- self.fileNameEdit = QtGui.QLineEdit(FileRenameDialog)
+ self.fileNameEdit = QtGui.QLineEdit(fileRenameDialog)
self.fileNameEdit.setValidator(QtGui.QRegExpValidator(
QtCore.QRegExp(r'[^/\\?*|<>\[\]":<>+%]+'), self))
self.fileNameEdit.setObjectName(u'fileNameEdit')
self.dialogLayout.addWidget(self.fileNameEdit, 0, 1)
- self.buttonBox = QtGui.QDialogButtonBox(FileRenameDialog)
- self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
- QtGui.QDialogButtonBox.Ok)
- self.buttonBox.setObjectName(u'buttonBox')
+ self.buttonBox = create_accept_reject_button_box(fileRenameDialog, True)
self.dialogLayout.addWidget(self.buttonBox, 1, 0, 1, 2)
- self.retranslateUi(FileRenameDialog)
+ self.retranslateUi(fileRenameDialog)
self.setMaximumHeight(self.sizeHint().height())
- QtCore.QMetaObject.connectSlotsByName(FileRenameDialog)
+ QtCore.QMetaObject.connectSlotsByName(fileRenameDialog)
- def retranslateUi(self, FileRenameDialog):
+ def retranslateUi(self, fileRenameDialog):
self.fileNameLabel.setText(translate('OpenLP.FileRenameForm',
'New File Name:'))
diff --git a/openlp/core/ui/filerenameform.py b/openlp/core/ui/filerenameform.py
index 86634e3b1..8b37cbc86 100644
--- a/openlp/core/ui/filerenameform.py
+++ b/openlp/core/ui/filerenameform.py
@@ -24,7 +24,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-from PyQt4 import QtCore, QtGui
+from PyQt4 import QtGui
from filerenamedialog import Ui_FileRenameDialog
@@ -37,10 +37,6 @@ class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog):
def __init__(self, parent):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
- QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'),
- self.accept)
- QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'),
- self.reject)
def exec_(self, copy=False):
"""
@@ -51,5 +47,5 @@ class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog):
'File Copy'))
else:
self.setWindowTitle(translate('OpenLP.FileRenameForm',
- 'File Rename'))
+ 'File Rename'))
return QtGui.QDialog.exec_(self)
diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py
index c4ab75aac..90042f80b 100644
--- a/openlp/core/ui/maindisplay.py
+++ b/openlp/core/ui/maindisplay.py
@@ -106,6 +106,9 @@ class MainDisplay(DisplayWidget):
self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject)
Phonon.createPath(self.mediaObject, self.videoWidget)
Phonon.createPath(self.mediaObject, self.audio)
+ QtCore.QObject.connect(self.mediaObject,
+ QtCore.SIGNAL(u'stateChanged(Phonon::State, Phonon::State)'),
+ self.videoStart)
self.webView = QtWebKit.QWebView(self)
self.webView.setGeometry(0, 0,
self.screen[u'size'].width(), self.screen[u'size'].height())
@@ -145,7 +148,7 @@ class MainDisplay(DisplayWidget):
serviceItem = ServiceItem()
serviceItem.bg_image_bytes = image_to_byte(initialFrame)
self.webView.setHtml(build_html(serviceItem, self.screen,
- self.parent.alertTab, self.isLive, None))
+ self.alertTab, self.isLive, None))
self.initialFrame = True
# To display or not to display?
if not self.screen[u'primary']:
@@ -341,6 +344,13 @@ class MainDisplay(DisplayWidget):
Receiver.send_message(u'maindisplay_active')
return self.preview()
+ def videoStart(self, newState, oldState):
+ """
+ Start the video at a predetermined point.
+ """
+ if newState == Phonon.PlayingState:
+ self.mediaObject.seek(self.serviceItem.start_time * 1000)
+
def isWebLoaded(self):
"""
Called by webView event to show display is fully loaded
@@ -406,7 +416,7 @@ class MainDisplay(DisplayWidget):
if self.serviceItem.themedata.background_filename:
self.serviceItem.bg_image_bytes = self.imageManager. \
get_image_bytes(self.serviceItem.themedata.theme_name)
- html = build_html(self.serviceItem, self.screen, self.parent.alertTab,
+ html = build_html(self.serviceItem, self.screen, self.alertTab,
self.isLive, background)
log.debug(u'buildHtml - pre setHtml')
self.webView.setHtml(html)
diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py
index c87a9544a..c691c006e 100644
--- a/openlp/core/ui/mainwindow.py
+++ b/openlp/core/ui/mainwindow.py
@@ -216,6 +216,9 @@ class Ui_MainWindow(object):
self.ToolsAddToolItem = icon_action(mainWindow, u'ToolsAddToolItem',
u':/tools/tools_add.png')
mainWindow.actionList.add_action(self.ToolsAddToolItem, u'Tools')
+ self.ToolsOpenDataFolder = icon_action(mainWindow,
+ u'ToolsOpenDataFolder', u':/general/general_open.png')
+ mainWindow.actionList.add_action(self.ToolsOpenDataFolder, u'Tools')
self.settingsPluginListItem = icon_action(mainWindow,
u'settingsPluginListItem', u':/system/settings_plugin_list.png')
mainWindow.actionList.add_action(self.settingsPluginListItem,
@@ -276,6 +279,7 @@ class Ui_MainWindow(object):
self.SettingsLanguageMenu.menuAction(), None,
self.SettingsShortcutsItem, self.SettingsConfigureItem))
add_actions(self.ToolsMenu, (self.ToolsAddToolItem, None))
+ add_actions(self.ToolsMenu, (self.ToolsOpenDataFolder, None))
add_actions(self.HelpMenu, (self.HelpDocumentationItem,
self.HelpOnlineHelpItem, None, self.HelpWebSiteItem,
self.HelpAboutItem))
@@ -315,20 +319,16 @@ class Ui_MainWindow(object):
self.themeManagerDock.setWindowTitle(
translate('OpenLP.MainWindow', 'Theme Manager'))
self.FileNewItem.setText(translate('OpenLP.MainWindow', '&New'))
- self.FileNewItem.setToolTip(
- translate('OpenLP.MainWindow', 'New Service'))
- self.FileNewItem.setStatusTip(
- translate('OpenLP.MainWindow', 'Create a new service.'))
+ self.FileNewItem.setToolTip(UiStrings.NewService)
+ self.FileNewItem.setStatusTip(UiStrings.CreateService)
self.FileNewItem.setShortcut(translate('OpenLP.MainWindow', 'Ctrl+N'))
self.FileOpenItem.setText(translate('OpenLP.MainWindow', '&Open'))
- self.FileOpenItem.setToolTip(
- translate('OpenLP.MainWindow', 'Open Service'))
+ self.FileOpenItem.setToolTip(UiStrings.OpenService)
self.FileOpenItem.setStatusTip(
translate('OpenLP.MainWindow', 'Open an existing service.'))
self.FileOpenItem.setShortcut(translate('OpenLP.MainWindow', 'Ctrl+O'))
self.FileSaveItem.setText(translate('OpenLP.MainWindow', '&Save'))
- self.FileSaveItem.setToolTip(
- translate('OpenLP.MainWindow', 'Save Service'))
+ self.FileSaveItem.setToolTip(UiStrings.SaveService)
self.FileSaveItem.setStatusTip(
translate('OpenLP.MainWindow', 'Save the current service to disk.'))
self.FileSaveItem.setShortcut(translate('OpenLP.MainWindow', 'Ctrl+S'))
@@ -433,6 +433,10 @@ class Ui_MainWindow(object):
translate('OpenLP.MainWindow', 'Add &Tool...'))
self.ToolsAddToolItem.setStatusTip(translate('OpenLP.MainWindow',
'Add an application to the list of tools.'))
+ self.ToolsOpenDataFolder.setText(
+ translate('OpenLP.MainWindow', 'Open &Data Folder...'))
+ self.ToolsOpenDataFolder.setStatusTip(translate('OpenLP.MainWindow',
+ 'Open the folder where songs, bibles and other data resides.'))
self.ModeDefaultItem.setText(
translate('OpenLP.MainWindow', '&Default'))
self.ModeDefaultItem.setStatusTip(translate('OpenLP.MainWindow',
@@ -515,6 +519,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.SIGNAL(u'triggered()'), self.onHelpWebSiteClicked)
QtCore.QObject.connect(self.HelpAboutItem,
QtCore.SIGNAL(u'triggered()'), self.onHelpAboutItemClicked)
+ QtCore.QObject.connect(self.ToolsOpenDataFolder,
+ QtCore.SIGNAL(u'triggered()'), self.onToolsOpenDataFolderClicked)
QtCore.QObject.connect(self.settingsPluginListItem,
QtCore.SIGNAL(u'triggered()'), self.onPluginItemClicked)
QtCore.QObject.connect(self.SettingsConfigureItem,
@@ -703,6 +709,13 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.pluginForm.load()
self.pluginForm.exec_()
+ def onToolsOpenDataFolderClicked(self):
+ """
+ Open data folder
+ """
+ path = AppLocation.get_data_path()
+ QtGui.QDesktopServices.openUrl(QtCore.QUrl("file:///" + path))
+
def onSettingsConfigureItemClicked(self):
"""
Show the Settings dialog
diff --git a/openlp/core/ui/printserviceorderform.py b/openlp/core/ui/printserviceorderform.py
index 3b01f9ac7..70128cb89 100644
--- a/openlp/core/ui/printserviceorderform.py
+++ b/openlp/core/ui/printserviceorderform.py
@@ -24,7 +24,6 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import datetime
-import mutagen
import os
from PyQt4 import QtCore, QtGui
@@ -113,16 +112,9 @@ class PrintServiceOrderForm(QtGui.QDialog, Ui_PrintServiceOrderDialog):
item.notes.replace(u'\n', u'
'))
# Add play length of media files.
if item.is_media() and self.printMetaDataCheckBox.isChecked():
- path = os.path.join(item.get_frames()[0][u'path'],
- item.get_frames()[0][u'title'])
- if not os.path.isfile(path):
- continue
- file = mutagen.File(path)
- if file is not None:
- length = int(file.info.length)
- text += u'
%s %s
' % (translate(
- 'OpenLP.ServiceManager', u'Playing time:'),
- unicode(datetime.timedelta(seconds=length)))
+ text += u'%s %s
' % (translate(
+ 'OpenLP.ServiceManager', u'Playing time:'),
+ unicode(datetime.timedelta(seconds=item.media_length)))
if self.customNoteEdit.toPlainText():
text += u'%s
%s' % (translate('OpenLP.ServiceManager',
u'Custom Service Notes:'), self.customNoteEdit.toPlainText())
diff --git a/openlp/core/ui/serviceitemeditdialog.py b/openlp/core/ui/serviceitemeditdialog.py
index f22f3dcf5..ef7e99a5f 100644
--- a/openlp/core/ui/serviceitemeditdialog.py
+++ b/openlp/core/ui/serviceitemeditdialog.py
@@ -27,7 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
-from openlp.core.lib.ui import create_save_cancel_button_box, \
+from openlp.core.lib.ui import create_accept_reject_button_box, \
create_delete_push_button, create_up_down_push_button_set
class Ui_ServiceItemEditDialog(object):
@@ -50,7 +50,7 @@ class Ui_ServiceItemEditDialog(object):
self.buttonLayout.addWidget(self.downButton)
self.dialogLayout.addLayout(self.buttonLayout, 0, 1)
self.dialogLayout.addWidget(
- create_save_cancel_button_box(serviceItemEditDialog), 1, 0, 1, 2)
+ create_accept_reject_button_box(serviceItemEditDialog), 1, 0, 1, 2)
self.retranslateUi(serviceItemEditDialog)
QtCore.QMetaObject.connectSlotsByName(serviceItemEditDialog)
diff --git a/openlp/core/ui/serviceitemeditform.py b/openlp/core/ui/serviceitemeditform.py
index 70518f30c..ae09cb0b2 100644
--- a/openlp/core/ui/serviceitemeditform.py
+++ b/openlp/core/ui/serviceitemeditform.py
@@ -110,11 +110,12 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
temp = self.itemList[row]
self.itemList.remove(self.itemList[row])
if direction == u'up':
- self.itemList.insert(row - 1, temp)
+ row -= 1
else:
- self.itemList.insert(row + 1, temp)
+ row += 1
+ self.itemList.insert(row, temp)
self.loadData()
- self.listWidget.setCurrentRow(row + 1)
+ self.listWidget.setCurrentRow(row)
def onCurrentRowChanged(self, row):
"""
diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py
index 079e2202c..623c2d641 100644
--- a/openlp/core/ui/servicemanager.py
+++ b/openlp/core/ui/servicemanager.py
@@ -35,8 +35,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, ServiceItem, context_menu_action, \
Receiver, build_icon, ItemCapabilities, SettingsManager, translate, \
ThemeLevel
-from openlp.core.lib.ui import critical_error_message_box
-from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm
+from openlp.core.lib.ui import UiStrings, critical_error_message_box
+from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
from openlp.core.ui.printserviceorderform import PrintServiceOrderForm
from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \
split_filename
@@ -88,6 +88,7 @@ class ServiceManager(QtGui.QWidget):
self._fileName = u''
self.serviceNoteForm = ServiceNoteForm(self.mainwindow)
self.serviceItemEditForm = ServiceItemEditForm(self.mainwindow)
+ self.startTimeForm = StartTimeForm(self.mainwindow)
# start with the layout
self.layout = QtGui.QVBoxLayout(self)
self.layout.setSpacing(0)
@@ -95,18 +96,14 @@ class ServiceManager(QtGui.QWidget):
# Create the top toolbar
self.toolbar = OpenLPToolbar(self)
self.toolbar.addToolbarButton(
- translate('OpenLP.ServiceManager', 'New Service'),
- u':/general/general_new.png',
- translate('OpenLP.ServiceManager', 'Create a new service'),
- self.onNewServiceClicked)
+ UiStrings.NewService, u':/general/general_new.png',
+ UiStrings.CreateService, self.onNewServiceClicked)
self.toolbar.addToolbarButton(
- translate('OpenLP.ServiceManager', 'Open Service'),
- u':/general/general_open.png',
+ UiStrings.OpenService, u':/general/general_open.png',
translate('OpenLP.ServiceManager', 'Load an existing service'),
self.onLoadServiceClicked)
self.toolbar.addToolbarButton(
- translate('OpenLP.ServiceManager', 'Save Service'),
- u':/general/general_save.png',
+ UiStrings.SaveService, u':/general/general_save.png',
translate('OpenLP.ServiceManager', 'Save this service'),
self.saveFile)
self.toolbar.addSeparator()
@@ -270,16 +267,19 @@ class ServiceManager(QtGui.QWidget):
self.notesAction = self.menu.addAction(
translate('OpenLP.ServiceManager', '&Notes'))
self.notesAction.setIcon(build_icon(u':/services/service_notes.png'))
+ self.timeAction = self.menu.addAction(
+ translate('OpenLP.ServiceManager', '&Start Time'))
+ self.timeAction.setIcon(build_icon(u':/media/media_time.png'))
self.deleteAction = self.menu.addAction(
translate('OpenLP.ServiceManager', '&Delete From Service'))
self.deleteAction.setIcon(build_icon(u':/general/general_delete.png'))
self.sep1 = self.menu.addAction(u'')
self.sep1.setSeparator(True)
self.previewAction = self.menu.addAction(
- translate('OpenLP.ServiceManager', '&Preview Verse'))
+ translate('OpenLP.ServiceManager', 'Show &Preview'))
self.previewAction.setIcon(build_icon(u':/general/general_preview.png'))
self.liveAction = self.menu.addAction(
- translate('OpenLP.ServiceManager', '&Live Verse'))
+ translate('OpenLP.ServiceManager', 'Show &Live'))
self.liveAction.setIcon(build_icon(u':/general/general_live.png'))
self.sep2 = self.menu.addAction(u'')
self.sep2.setSeparator(True)
@@ -465,7 +465,7 @@ class ServiceManager(QtGui.QWidget):
save the file.
"""
fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.mainwindow,
- translate('OpenLP.ServiceManager', 'Save Service'),
+ UiStrings.SaveService,
SettingsManager.get_last_dir(
self.mainwindow.serviceSettingsSection),
translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)')))
@@ -563,6 +563,7 @@ class ServiceManager(QtGui.QWidget):
self.editAction.setVisible(False)
self.maintainAction.setVisible(False)
self.notesAction.setVisible(False)
+ self.timeAction.setVisible(False)
if serviceItem[u'service_item'].is_capable(ItemCapabilities.AllowsEdit)\
and serviceItem[u'service_item'].edit_id:
self.editAction.setVisible(True)
@@ -571,6 +572,9 @@ class ServiceManager(QtGui.QWidget):
self.maintainAction.setVisible(True)
if item.parent() is None:
self.notesAction.setVisible(True)
+ if serviceItem[u'service_item']\
+ .is_capable(ItemCapabilities.AllowsVarableStartTime):
+ self.timeAction.setVisible(True)
self.themeMenu.menuAction().setVisible(False)
if serviceItem[u'service_item'].is_text():
self.themeMenu.menuAction().setVisible(True)
@@ -583,6 +587,8 @@ class ServiceManager(QtGui.QWidget):
self.onDeleteFromService()
if action == self.notesAction:
self.onServiceItemNoteForm()
+ if action == self.timeAction:
+ self.onStartTimeForm()
if action == self.previewAction:
self.makePreview()
if action == self.liveAction:
@@ -597,6 +603,16 @@ class ServiceManager(QtGui.QWidget):
self.serviceNoteForm.textEdit.toPlainText()
self.repaintServiceList(item, -1)
+ def onStartTimeForm(self):
+ item = self.findServiceItem()[0]
+ self.startTimeForm.item = self.serviceItems[item]
+ if self.startTimeForm.exec_():
+ self.serviceItems[item][u'service_item'].start_time = \
+ self.startTimeForm.hourSpinBox.value() * 3600 + \
+ self.startTimeForm.minuteSpinBox.value() * 60 + \
+ self.startTimeForm.secondSpinBox.value()
+ self.repaintServiceList(item, -1)
+
def onServiceItemEditForm(self):
item = self.findServiceItem()[0]
self.serviceItemEditForm.setServiceItem(
@@ -843,6 +859,11 @@ class ServiceManager(QtGui.QWidget):
text = frame[u'title'].replace(u'\n', u' ')
child.setText(0, text[:40])
child.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(count))
+ if item[u'service_item'] \
+ .is_capable(ItemCapabilities.AllowsVarableStartTime):
+ tip = item[u'service_item'].get_media_time()
+ if tip:
+ child.setToolTip(0, tip)
if serviceItem == itemcount:
if item[u'expanded'] and serviceItemChild == count:
self.serviceManagerList.setCurrentItem(child)
diff --git a/openlp/core/ui/servicenoteform.py b/openlp/core/ui/servicenoteform.py
index 473cc1685..a12b693f8 100644
--- a/openlp/core/ui/servicenoteform.py
+++ b/openlp/core/ui/servicenoteform.py
@@ -27,7 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
-from openlp.core.lib.ui import create_save_cancel_button_box
+from openlp.core.lib.ui import create_accept_reject_button_box
class ServiceNoteForm(QtGui.QDialog):
"""
@@ -48,7 +48,7 @@ class ServiceNoteForm(QtGui.QDialog):
self.textEdit = QtGui.QTextEdit(self)
self.textEdit.setObjectName(u'textEdit')
self.dialogLayout.addWidget(self.textEdit)
- self.dialogLayout.addWidget(create_save_cancel_button_box(self))
+ self.dialogLayout.addWidget(create_accept_reject_button_box(self))
QtCore.QMetaObject.connectSlotsByName(self)
def retranslateUi(self):
diff --git a/openlp/core/ui/settingsdialog.py b/openlp/core/ui/settingsdialog.py
index 61c73961c..99acadc14 100644
--- a/openlp/core/ui/settingsdialog.py
+++ b/openlp/core/ui/settingsdialog.py
@@ -27,6 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, build_icon
+from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_SettingsDialog(object):
def setupUi(self, settingsDialog):
@@ -40,16 +41,9 @@ class Ui_SettingsDialog(object):
self.settingsTabWidget = QtGui.QTabWidget(settingsDialog)
self.settingsTabWidget.setObjectName(u'settingsTabWidget')
self.settingsLayout.addWidget(self.settingsTabWidget)
- self.buttonBox = QtGui.QDialogButtonBox(settingsDialog)
- self.buttonBox.setStandardButtons(
- QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok)
- self.buttonBox.setObjectName(u'buttonBox')
+ self.buttonBox = create_accept_reject_button_box(settingsDialog, True)
self.settingsLayout.addWidget(self.buttonBox)
self.retranslateUi(settingsDialog)
- QtCore.QObject.connect(self.buttonBox,
- QtCore.SIGNAL(u'accepted()'), settingsDialog.accept)
- QtCore.QObject.connect(self.buttonBox,
- QtCore.SIGNAL(u'rejected()'), settingsDialog.reject)
QtCore.QMetaObject.connectSlotsByName(settingsDialog)
def retranslateUi(self, settingsDialog):
diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py
index c6b58ac56..52626f24f 100644
--- a/openlp/core/ui/slidecontroller.py
+++ b/openlp/core/ui/slidecontroller.py
@@ -877,7 +877,7 @@ class SlideController(QtGui.QWidget):
using *Blank to Theme*.
"""
log.debug(u'updatePreview %s ' % self.screens.current[u'primary'])
- if not self.screens.current[u'primary'] and \
+ if not self.screens.current[u'primary'] and self.serviceItem and \
self.serviceItem.is_capable(ItemCapabilities.ProvidesOwnDisplay):
# Grab now, but try again in a couple of seconds if slide change
# is slow
diff --git a/openlp/core/ui/starttimedialog.py b/openlp/core/ui/starttimedialog.py
new file mode 100644
index 000000000..8dcc2c9ee
--- /dev/null
+++ b/openlp/core/ui/starttimedialog.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
+# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard, Frode Woldsund #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from PyQt4 import QtCore, QtGui
+
+from openlp.core.lib import translate
+from openlp.core.lib.ui import create_accept_reject_button_box
+
+class Ui_StartTimeDialog(object):
+ def setupUi(self, StartTimeDialog):
+ StartTimeDialog.setObjectName(u'StartTimeDialog')
+ StartTimeDialog.resize(300, 10)
+ self.dialogLayout = QtGui.QGridLayout(StartTimeDialog)
+ self.dialogLayout.setObjectName(u'dialogLayout')
+ self.hourLabel = QtGui.QLabel(StartTimeDialog)
+ self.hourLabel.setObjectName("hourLabel")
+ self.dialogLayout.addWidget(self.hourLabel, 0, 0, 1, 1)
+ self.hourSpinBox = QtGui.QSpinBox(StartTimeDialog)
+ self.hourSpinBox.setObjectName("hourSpinBox")
+ self.dialogLayout.addWidget(self.hourSpinBox, 0, 1, 1, 1)
+ self.minuteLabel = QtGui.QLabel(StartTimeDialog)
+ self.minuteLabel.setObjectName("minuteLabel")
+ self.dialogLayout.addWidget(self.minuteLabel, 1, 0, 1, 1)
+ self.minuteSpinBox = QtGui.QSpinBox(StartTimeDialog)
+ self.minuteSpinBox.setObjectName("minuteSpinBox")
+ self.dialogLayout.addWidget(self.minuteSpinBox, 1, 1, 1, 1)
+ self.secondLabel = QtGui.QLabel(StartTimeDialog)
+ self.secondLabel.setObjectName("secondLabel")
+ self.dialogLayout.addWidget(self.secondLabel, 2, 0, 1, 1)
+ self.secondSpinBox = QtGui.QSpinBox(StartTimeDialog)
+ self.secondSpinBox.setObjectName("secondSpinBox")
+ self.dialogLayout.addWidget(self.secondSpinBox, 2, 1, 1, 1)
+ self.buttonBox = create_accept_reject_button_box(StartTimeDialog, True)
+ self.dialogLayout.addWidget(self.buttonBox, 4, 0, 1, 2)
+ self.retranslateUi(StartTimeDialog)
+ self.setMaximumHeight(self.sizeHint().height())
+ QtCore.QMetaObject.connectSlotsByName(StartTimeDialog)
+
+ def retranslateUi(self, StartTimeDialog):
+ self.setWindowTitle(translate('OpenLP.StartTimeForm',
+ 'Item Start Time'))
+ self.hourLabel.setText(translate('OpenLP.StartTimeForm', 'Hours:'))
+ self.hourSpinBox.setSuffix(translate('OpenLP.StartTimeForm', 'h'))
+ self.minuteSpinBox.setSuffix(translate('OpenLP.StartTimeForm', 'm'))
+ self.secondSpinBox.setSuffix(translate('OpenLP.StartTimeForm', 's'))
+ self.minuteLabel.setText(translate('OpenLP.StartTimeForm', 'Minutes:'))
+ self.secondLabel.setText(translate('OpenLP.StartTimeForm', 'Seconds:'))
diff --git a/openlp/core/ui/starttimeform.py b/openlp/core/ui/starttimeform.py
new file mode 100644
index 000000000..1280931d5
--- /dev/null
+++ b/openlp/core/ui/starttimeform.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
+# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard, Frode Woldsund #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from PyQt4 import QtGui
+
+from starttimedialog import Ui_StartTimeDialog
+
+class StartTimeForm(QtGui.QDialog, Ui_StartTimeDialog):
+ """
+ The exception dialog
+ """
+ def __init__(self, parent):
+ QtGui.QDialog.__init__(self, parent)
+ self.setupUi(self)
+
+ def exec_(self):
+ """
+ Run the Dialog with correct heading.
+ """
+ seconds = self.item[u'service_item'].start_time
+ hours = seconds / 3600
+ seconds -= 3600 * hours
+ minutes = seconds / 60
+ seconds -= 60 * minutes
+ self.hourSpinBox.setValue(hours)
+ self.minuteSpinBox.setValue(minutes)
+ self.secondSpinBox.setValue(seconds)
+ return QtGui.QDialog.exec_(self)
+
diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py
index f86fa0143..ad9e80d66 100644
--- a/openlp/core/ui/themeform.py
+++ b/openlp/core/ui/themeform.py
@@ -483,7 +483,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
Background Image button pushed.
"""
images_filter = get_images_filter()
- images_filter = '%s;;%s (*.*) (*)' % (images_filter, UiStrings.AllFiles)
+ images_filter = u'%s;;%s (*.*) (*)' % (
+ images_filter, UiStrings.AllFiles)
filename = QtGui.QFileDialog.getOpenFileName(self,
translate('OpenLP.ThemeForm', 'Select Image'), u'',
images_filter)
diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py
index 93a5ef187..69028ad76 100644
--- a/openlp/core/ui/thememanager.py
+++ b/openlp/core/ui/thememanager.py
@@ -34,7 +34,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \
build_icon, Receiver, SettingsManager, translate, check_item_selected, \
- BackgroundType, BackgroundGradientType, check_directory_exists
+ BackgroundType, BackgroundGradientType, check_directory_exists, \
+ VerticalType
from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.theme import Theme
from openlp.core.ui import FileRenameForm, ThemeForm
@@ -62,28 +63,28 @@ class ThemeManager(QtGui.QWidget):
self.layout.setObjectName(u'layout')
self.toolbar = OpenLPToolbar(self)
self.toolbar.addToolbarButton(
- UiStrings.NewType % UiStrings.Theme,
+ translate('OpenLP.ThemeManager', 'New Theme'),
u':/themes/theme_new.png',
translate('OpenLP.ThemeManager', 'Create a new theme.'),
self.onAddTheme)
self.toolbar.addToolbarButton(
- UiStrings.EditType % UiStrings.Theme,
+ translate('OpenLP.ThemeManager', 'Edit Theme'),
u':/themes/theme_edit.png',
translate('OpenLP.ThemeManager', 'Edit a theme.'),
self.onEditTheme)
self.deleteToolbarAction = self.toolbar.addToolbarButton(
- UiStrings.DeleteType % UiStrings.Theme,
+ translate('OpenLP.ThemeManager', 'Delete Theme'),
u':/general/general_delete.png',
translate('OpenLP.ThemeManager', 'Delete a theme.'),
self.onDeleteTheme)
self.toolbar.addSeparator()
self.toolbar.addToolbarButton(
- UiStrings.ImportType % UiStrings.Theme,
+ translate('OpenLP.ThemeManager', 'Import Theme'),
u':/general/general_import.png',
translate('OpenLP.ThemeManager', 'Import a theme.'),
self.onImportTheme)
self.toolbar.addToolbarButton(
- UiStrings.ExportType % UiStrings.Theme,
+ translate('OpenLP.ThemeManager', 'Export Theme'),
u':/general/general_export.png',
translate('OpenLP.ThemeManager', 'Export a theme.'),
self.onExportTheme)
@@ -405,8 +406,8 @@ class ThemeManager(QtGui.QWidget):
files = QtGui.QFileDialog.getOpenFileNames(self,
translate('OpenLP.ThemeManager', 'Select Theme Import File'),
SettingsManager.get_last_dir(self.settingsSection),
- translate('OpenLP.ThemeManager', 'Theme v1 (*.theme);;'
- 'Theme v2 (*.otz);;All Files (*.*)'))
+ unicode(translate('OpenLP.ThemeManager', 'Theme v1 (*.theme);;'
+ 'Theme v2 (*.otz);;%s (*.*)')) % UiStrings.AllFiles)
log.info(u'New Themes %s', unicode(files))
if files:
for file in files:
@@ -762,11 +763,11 @@ class ThemeManager(QtGui.QWidget):
newtheme.font_main_outline = True
newtheme.font_main_outline_color = \
unicode(theme.OutlineColor.name())
- vAlignCorrection = 0
+ vAlignCorrection = VerticalType.Top
if theme.VerticalAlign == 2:
- vAlignCorrection = 1
+ vAlignCorrection = VerticalType.Middle
elif theme.VerticalAlign == 1:
- vAlignCorrection = 2
+ vAlignCorrection = VerticalType.Bottom
newtheme.display_horizontal_align = theme.HorizontalAlign
newtheme.display_vertical_align = vAlignCorrection
return newtheme.extract_xml()
diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py
index 2fa448db8..d3410ded9 100644
--- a/openlp/core/ui/wizard.py
+++ b/openlp/core/ui/wizard.py
@@ -27,11 +27,12 @@
The :mod:``wizard`` module provides generic wizard tools for OpenLP.
"""
import logging
+import os
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import build_icon, Receiver
-from openlp.core.lib.ui import add_welcome_page
+from openlp.core.lib import build_icon, Receiver, SettingsManager
+from openlp.core.lib.ui import UiStrings, add_welcome_page
log = logging.getLogger(__name__)
@@ -70,6 +71,12 @@ class OpenLPWizard(QtGui.QWizard):
self.retranslateUi()
QtCore.QMetaObject.connectSlotsByName(self)
+ def registerFields(self):
+ """
+ Hook method for wizards to register any fields they need.
+ """
+ pass
+
def addProgressPage(self):
"""
Add the progress page for the wizard. This page informs the user how
@@ -146,3 +153,30 @@ class OpenLPWizard(QtGui.QWizard):
self.finishButton.setVisible(True)
self.cancelButton.setVisible(False)
Receiver.send_message(u'openlp_process_events')
+
+ def getFileName(self, title, editbox, filters=u''):
+ """
+ Opens a QFileDialog and saves the filename to the given editbox.
+
+ ``title``
+ The title of the dialog (unicode).
+
+ ``editbox``
+ A editbox (QLineEdit).
+
+ ``filters``
+ The file extension filters. It should contain the file description
+ as well as the file extension. For example::
+
+ u'OpenLP 2.0 Databases (*.sqlite)'
+ """
+ if filters:
+ filters += u';;'
+ filters += u'%s (*)' % UiStrings.AllFiles
+ filename = QtGui.QFileDialog.getOpenFileName(self, title,
+ os.path.dirname(SettingsManager.get_last_dir(
+ self.plugin.settingsSection, 1)), filters)
+ if filename:
+ editbox.setText(filename)
+ SettingsManager.set_last_dir(self.plugin.settingsSection,
+ filename, 1)
diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py
index 2862afef4..9db744460 100644
--- a/openlp/core/utils/__init__.py
+++ b/openlp/core/utils/__init__.py
@@ -165,6 +165,8 @@ def _get_os_dir_path(dir_type):
Return a path based on which OS and environment we are running in.
"""
if sys.platform == u'win32':
+ if dir_type == AppLocation.DataDir:
+ return os.path.join(os.getenv(u'APPDATA'), u'openlp', u'data')
return os.path.join(os.getenv(u'APPDATA'), u'openlp')
elif sys.platform == u'darwin':
if dir_type == AppLocation.DataDir:
@@ -180,8 +182,9 @@ def _get_os_dir_path(dir_type):
return os.path.join(BaseDirectory.xdg_data_home, u'openlp')
elif dir_type == AppLocation.CacheDir:
return os.path.join(BaseDirectory.xdg_cache_home, u'openlp')
- else:
- return os.path.join(os.getenv(u'HOME'), u'.openlp')
+ if dir_type == AppLocation.DataDir:
+ return os.path.join(os.getenv(u'HOME'), u'.openlp', u'data')
+ return os.path.join(os.getenv(u'HOME'), u'.openlp')
def _get_frozen_path(frozen_option, non_frozen_option):
"""
@@ -189,8 +192,7 @@ def _get_frozen_path(frozen_option, non_frozen_option):
"""
if hasattr(sys, u'frozen') and sys.frozen == 1:
return frozen_option
- else:
- return non_frozen_option
+ return non_frozen_option
def check_latest_version(current_version):
"""
diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py
index 443ec1e84..136d775a5 100644
--- a/openlp/plugins/alerts/alertsplugin.py
+++ b/openlp/plugins/alerts/alertsplugin.py
@@ -40,21 +40,14 @@ class AlertsPlugin(Plugin):
log.info(u'Alerts Plugin loaded')
def __init__(self, plugin_helpers):
- Plugin.__init__(self, u'Alerts', u'1.9.4', plugin_helpers)
+ Plugin.__init__(self, u'Alerts', u'1.9.4', plugin_helpers,
+ settingsTabClass=AlertsTab)
self.weight = -3
self.icon = build_icon(u':/plugins/plugin_alerts.png')
self.alertsmanager = AlertsManager(self)
self.manager = Manager(u'alerts', init_schema)
- self.visible_name = self.getString(StringContent.VisibleName)
self.alertForm = AlertForm(self)
- def getSettingsTab(self):
- """
- Return the settings tab for the Alerts plugin
- """
- self.alertsTab = AlertsTab(self, self.visible_name[u'title'])
- return self.alertsTab
-
def addToolsMenuItem(self, tools_menu):
"""
Give the alerts plugin the opportunity to add items to the
@@ -81,7 +74,7 @@ class AlertsPlugin(Plugin):
log.info(u'Alerts Initialising')
Plugin.initialise(self)
self.toolsAlertItem.setVisible(True)
- self.liveController.alertTab = self.alertsTab
+ self.liveController.alertTab = self.settings_tab
def finalise(self):
"""
diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py
index 6fe0ae132..f69099bf1 100644
--- a/openlp/plugins/alerts/lib/alertsmanager.py
+++ b/openlp/plugins/alerts/lib/alertsmanager.py
@@ -84,7 +84,7 @@ class AlertsManager(QtCore.QObject):
if len(self.alertList) == 0:
return
text = self.alertList.pop(0)
- alertTab = self.parent.alertsTab
+ alertTab = self.parent.settings_tab
self.parent.liveController.display.alert(text)
# Check to see if we have a timer running.
if self.timer_id == 0:
@@ -103,4 +103,4 @@ class AlertsManager(QtCore.QObject):
self.parent.liveController.display.alert(u'')
self.killTimer(self.timer_id)
self.timer_id = 0
- self.generateAlert()
\ No newline at end of file
+ self.generateAlert()
diff --git a/openlp/plugins/alerts/lib/alertstab.py b/openlp/plugins/alerts/lib/alertstab.py
index 4090503db..48a4527ed 100644
--- a/openlp/plugins/alerts/lib/alertstab.py
+++ b/openlp/plugins/alerts/lib/alertstab.py
@@ -33,10 +33,8 @@ class AlertsTab(SettingsTab):
"""
AlertsTab is the alerts settings tab in the settings dialog.
"""
- def __init__(self, parent, visible_title):
- self.parent = parent
- self.manager = parent.manager
- SettingsTab.__init__(self, parent.name, visible_title)
+ def __init__(self, name, visible_title):
+ SettingsTab.__init__(self, name, visible_title)
def setupUi(self):
self.setObjectName(u'AlertsTab')
diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py
index 89102a8eb..de0ea11f1 100644
--- a/openlp/plugins/bibles/bibleplugin.py
+++ b/openlp/plugins/bibles/bibleplugin.py
@@ -38,7 +38,8 @@ class BiblePlugin(Plugin):
log.info(u'Bible Plugin loaded')
def __init__(self, plugin_helpers):
- Plugin.__init__(self, u'Bibles', u'1.9.4', plugin_helpers)
+ Plugin.__init__(self, u'Bibles', u'1.9.4', plugin_helpers,
+ BibleMediaItem, BiblesTab)
self.weight = -9
self.icon_path = u':/plugins/plugin_bibles.png'
self.icon = build_icon(self.icon_path)
@@ -62,14 +63,6 @@ class BiblePlugin(Plugin):
self.importBibleItem.setVisible(False)
self.exportBibleItem.setVisible(False)
- def getSettingsTab(self):
- visible_name = self.getString(StringContent.VisibleName)
- return BiblesTab(self.name, visible_name[u'title'])
-
- def getMediaManagerItem(self):
- # Create the BibleManagerItem object.
- return BibleMediaItem(self, self, self.icon)
-
def addImportMenuItem(self, import_menu):
self.importBibleItem = QtGui.QAction(import_menu)
self.importBibleItem.setObjectName(u'importBibleItem')
@@ -136,9 +129,15 @@ class BiblePlugin(Plugin):
u'title': translate('BiblesPlugin', 'Bibles', 'container title')
}
# Middle Header Bar
- ## Import Action ##
- self.textStrings[StringContent.Import] = {
- u'title': UiStrings.Import,
- u'tooltip': translate('BiblesPlugin', 'Import a Bible')
+ tooltips = {
+ u'load': u'',
+ u'import': translate('BiblesPlugin', 'Import a Bible'),
+ u'new': translate('BiblesPlugin', 'Add a new Bible'),
+ u'edit': translate('BiblesPlugin', 'Edit the selected Bible'),
+ u'delete': translate('BiblesPlugin', 'Delete the selected Bible'),
+ u'preview': translate('BiblesPlugin', 'Preview the selected Bible'),
+ u'live': translate('BiblesPlugin', 'Send the selected Bible live'),
+ u'service': translate('BiblesPlugin',
+ 'Add the selected Bible to the service')
}
- Plugin.setPluginTextStrings(self)
+ self.setPluginUiTextStrings(tooltips)
diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py
index f528a4b1b..463c838c9 100644
--- a/openlp/plugins/bibles/forms/bibleimportform.py
+++ b/openlp/plugins/bibles/forms/bibleimportform.py
@@ -33,9 +33,9 @@ import os.path
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import Receiver, SettingsManager, translate
+from openlp.core.lib import Receiver, translate
from openlp.core.lib.db import delete_database
-from openlp.core.lib.ui import UiStrings, critical_error_message_box
+from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard
from openlp.core.utils import AppLocation, string_is_unicode
from openlp.plugins.bibles.lib.manager import BibleFormat
@@ -727,33 +727,6 @@ class BibleImportForm(OpenLPWizard):
if books_file:
books_file.close()
- def getFileName(self, title, editbox, filters=u''):
- """
- Opens a QFileDialog and saves the filename to the given editbox.
-
- ``title``
- The title of the dialog (unicode).
-
- ``editbox``
- A editbox (QLineEdit).
-
- ``filters``
- The file extension filters. It should contain the file description
- as well as the file extension. For example::
-
- u'openlp.org 1.x bible (*.bible)'
- """
- if filters:
- filters += u';;'
- filters += u'%s (*)' % UiStrings.AllFiles
- filename = QtGui.QFileDialog.getOpenFileName(self, title,
- os.path.dirname(SettingsManager.get_last_dir(
- self.plugin.settingsSection, 1)), filters)
- if filename:
- editbox.setText(filename)
- SettingsManager.set_last_dir(
- self.plugin.settingsSection, filename, 1)
-
def preWizard(self):
"""
Prepare the UI for the import.
diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py
index c162447b2..a6ceba6ac 100644
--- a/openlp/plugins/bibles/lib/mediaitem.py
+++ b/openlp/plugins/bibles/lib/mediaitem.py
@@ -28,22 +28,22 @@ import logging
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \
- ItemCapabilities, translate
-from openlp.core.lib.ui import add_widget_completer, media_item_combo_box, \
- critical_error_message_box
+from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
+ translate
+from openlp.core.lib.searchedit import SearchEdit
+from openlp.core.lib.ui import UiStrings, add_widget_completer, \
+ media_item_combo_box, critical_error_message_box
from openlp.plugins.bibles.forms import BibleImportForm
from openlp.plugins.bibles.lib import get_reference_match
log = logging.getLogger(__name__)
-class BibleListView(BaseListWithDnD):
+class BibleSearch(object):
"""
- Custom list view descendant, required for drag and drop.
+ Enumeration class for the different search methods for the "quick search".
"""
- def __init__(self, parent=None):
- self.PluginName = u'Bibles'
- BaseListWithDnD.__init__(self, parent)
+ Reference = 1
+ Text = 2
class BibleMediaItem(MediaManagerItem):
@@ -54,7 +54,6 @@ class BibleMediaItem(MediaManagerItem):
def __init__(self, parent, plugin, icon):
self.IconPath = u'songs/song'
- self.ListViewWithDnD_class = BibleListView
MediaManagerItem.__init__(self, parent, plugin, icon)
# Place to store the search results for both bibles.
self.search_results = {}
@@ -93,18 +92,17 @@ class BibleMediaItem(MediaManagerItem):
u'quickSecondComboBox')
self.quickSecondLabel.setBuddy(self.quickSecondComboBox)
self.quickLayout.addRow(self.quickSecondLabel, self.quickSecondComboBox)
- self.quickSearchTypeLabel = QtGui.QLabel(self.quickTab)
- self.quickSearchTypeLabel.setObjectName(u'quickSearchTypeLabel')
- self.quickSearchComboBox = media_item_combo_box(self.quickTab,
- u'quickSearchComboBox')
- self.quickSearchTypeLabel.setBuddy(self.quickSearchComboBox)
- self.quickLayout.addRow(self.quickSearchTypeLabel,
- self.quickSearchComboBox)
self.quickSearchLabel = QtGui.QLabel(self.quickTab)
self.quickSearchLabel.setObjectName(u'quickSearchLabel')
- self.quickSearchEdit = QtGui.QLineEdit(self.quickTab)
+ self.quickSearchEdit = SearchEdit(self.quickTab)
self.quickSearchEdit.setObjectName(u'quickSearchEdit')
self.quickSearchLabel.setBuddy(self.quickSearchEdit)
+ self.quickSearchEdit.setSearchTypes([
+ (BibleSearch.Reference, u':/bibles/bibles_search_reference.png',
+ translate('BiblesPlugin.MediaItem', 'Scripture Reference')),
+ (BibleSearch.Text, u':/bibles/bibles_search_text.png',
+ translate('BiblesPlugin.MediaItem', 'Text Search'))
+ ])
self.quickLayout.addRow(self.quickSearchLabel, self.quickSearchEdit)
self.quickClearLabel = QtGui.QLabel(self.quickTab)
self.quickClearLabel.setObjectName(u'quickClearLabel')
@@ -192,8 +190,7 @@ class BibleMediaItem(MediaManagerItem):
self.advancedSearchButtonLayout.addWidget(self.advancedSearchButton)
self.advancedLayout.addLayout(
self.advancedSearchButtonLayout, 7, 0, 1, 3)
- self.searchTabWidget.addTab(self.advancedTab,
- translate('BiblesPlugin.MediaItem', 'Advanced'))
+ self.searchTabWidget.addTab(self.advancedTab, UiStrings.Advanced)
# Add the search tab widget to the page layout.
self.pageLayout.addWidget(self.searchTabWidget)
# Combo Boxes
@@ -207,8 +204,8 @@ class BibleMediaItem(MediaManagerItem):
QtCore.SIGNAL(u'activated(int)'), self.onAdvancedFromVerse)
QtCore.QObject.connect(self.advancedToChapter,
QtCore.SIGNAL(u'activated(int)'), self.onAdvancedToChapter)
- QtCore.QObject.connect(self.quickSearchComboBox,
- QtCore.SIGNAL(u'activated(int)'), self.updateAutoCompleter)
+ QtCore.QObject.connect(self.quickSearchEdit,
+ QtCore.SIGNAL(u'searchTypeChanged(int)'), self.updateAutoCompleter)
QtCore.QObject.connect(self.quickVersionComboBox,
QtCore.SIGNAL(u'activated(int)'), self.updateAutoCompleter)
# Buttons
@@ -242,8 +239,6 @@ class BibleMediaItem(MediaManagerItem):
translate('BiblesPlugin.MediaItem', 'Version:'))
self.quickSecondLabel.setText(
translate('BiblesPlugin.MediaItem', 'Second:'))
- self.quickSearchTypeLabel.setText(
- translate('BiblesPlugin.MediaItem', 'Search type:'))
self.quickSearchLabel.setText(
translate('BiblesPlugin.MediaItem', 'Find:'))
self.quickSearchButton.setText(
@@ -268,10 +263,6 @@ class BibleMediaItem(MediaManagerItem):
translate('BiblesPlugin.MediaItem', 'Results:'))
self.advancedSearchButton.setText(
translate('BiblesPlugin.MediaItem', 'Search'))
- self.quickSearchComboBox.addItem(
- translate('BiblesPlugin.MediaItem', 'Verse Search'))
- self.quickSearchComboBox.addItem(
- translate('BiblesPlugin.MediaItem', 'Text Search'))
self.quickClearComboBox.addItem(
translate('BiblesPlugin.MediaItem', 'Clear'))
self.quickClearComboBox.addItem(
@@ -369,11 +360,11 @@ class BibleMediaItem(MediaManagerItem):
"""
This updates the bible book completion list for the search field. The
completion depends on the bible. It is only updated when we are doing a
- verse search, otherwise the auto completion list is removed.
+ reference search, otherwise the auto completion list is removed.
"""
books = []
- # We have to do a 'Verse Search'.
- if self.quickSearchComboBox.currentIndex() == 0:
+ # We have to do a 'Reference Search'.
+ if self.quickSearchEdit.currentSearchType() == BibleSearch.Reference:
bibles = self.parent.manager.get_bibles()
bible = unicode(self.quickVersionComboBox.currentText())
if bible:
@@ -502,7 +493,7 @@ class BibleMediaItem(MediaManagerItem):
def onQuickSearchButton(self):
"""
Does a quick search and saves the search results. Quick search can
- either be "Verse Search" or "Text Search".
+ either be "Reference Search" or "Text Search".
"""
log.debug(u'Quick Search Button pressed')
self.quickSearchButton.setEnabled(False)
@@ -510,8 +501,8 @@ class BibleMediaItem(MediaManagerItem):
bible = unicode(self.quickVersionComboBox.currentText())
second_bible = unicode(self.quickSecondComboBox.currentText())
text = unicode(self.quickSearchEdit.text())
- if self.quickSearchComboBox.currentIndex() == 0:
- # We are doing a 'Verse Search'.
+ if self.quickSearchEdit.currentSearchType() == BibleSearch.Reference:
+ # We are doing a 'Reference Search'.
self.search_results = self.parent.manager.get_verses(bible, text)
if second_bible and self.search_results:
self.second_search_results = self.parent.manager.get_verses(
diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py
index f20fbc9cd..5a32d4657 100644
--- a/openlp/plugins/custom/customplugin.py
+++ b/openlp/plugins/custom/customplugin.py
@@ -48,21 +48,14 @@ class CustomPlugin(Plugin):
log.info(u'Custom Plugin loaded')
def __init__(self, plugin_helpers):
- Plugin.__init__(self, u'Custom', u'1.9.4', plugin_helpers)
+ Plugin.__init__(self, u'Custom', u'1.9.4', plugin_helpers,
+ CustomMediaItem, CustomTab)
self.weight = -5
self.manager = Manager(u'custom', init_schema)
self.edit_custom_form = EditCustomForm(self.manager)
self.icon_path = u':/plugins/plugin_custom.png'
self.icon = build_icon(self.icon_path)
- def getSettingsTab(self):
- visible_name = self.getString(StringContent.VisibleName)
- return CustomTab(self.name, visible_name[u'title'])
-
- def getMediaManagerItem(self):
- # Create the ManagerItem object
- return CustomMediaItem(self, self, self.icon)
-
def about(self):
about_text = translate('CustomPlugin', 'Custom Plugin'
'
The custom plugin provides the ability to set up custom '
@@ -113,13 +106,20 @@ class CustomPlugin(Plugin):
u'title': translate('CustomsPlugin', 'Custom', 'container title')
}
# Middle Header Bar
- ## Import Action ##
- self.textStrings[StringContent.Import] = {
- u'title': UiStrings.Import,
- u'tooltip': translate('CustomsPlugin',
- 'Import a Custom')
+ tooltips = {
+ u'load': translate('CustomsPlugin', 'Load a new Custom'),
+ u'import': translate('CustomsPlugin', 'Import a Custom'),
+ u'new': translate('CustomsPlugin', 'Add a new Custom'),
+ u'edit': translate('CustomsPlugin', 'Edit the selected Custom'),
+ u'delete': translate('CustomsPlugin', 'Delete the selected Custom'),
+ u'preview': translate('CustomsPlugin',
+ 'Preview the selected Custom'),
+ u'live': translate('CustomsPlugin',
+ 'Send the selected Custom live'),
+ u'service': translate('CustomsPlugin',
+ 'Add the selected Custom to the service')
}
- Plugin.setPluginTextStrings(self)
+ self.setPluginUiTextStrings(tooltips)
def finalise(self):
"""
diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py
index 1ca29732b..2e8a64a9d 100644
--- a/openlp/plugins/custom/forms/editcustomdialog.py
+++ b/openlp/plugins/custom/forms/editcustomdialog.py
@@ -27,7 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon, translate
-from openlp.core.lib.ui import UiStrings, create_save_cancel_button_box, \
+from openlp.core.lib.ui import UiStrings, create_accept_reject_button_box, \
create_delete_push_button, create_up_down_push_button_set
class Ui_CustomEditDialog(object):
@@ -94,7 +94,7 @@ class Ui_CustomEditDialog(object):
self.creditLabel.setBuddy(self.creditEdit)
self.bottomFormLayout.addRow(self.creditLabel, self.creditEdit)
self.dialogLayout.addLayout(self.bottomFormLayout)
- self.buttonBox = create_save_cancel_button_box(customEditDialog)
+ self.buttonBox = create_accept_reject_button_box(customEditDialog)
self.previewButton = QtGui.QPushButton()
self.buttonBox.addButton(
self.previewButton, QtGui.QDialogButtonBox.ActionRole)
diff --git a/openlp/plugins/custom/forms/editcustomslidedialog.py b/openlp/plugins/custom/forms/editcustomslidedialog.py
index 24c40d6e6..b70e2bf5e 100644
--- a/openlp/plugins/custom/forms/editcustomslidedialog.py
+++ b/openlp/plugins/custom/forms/editcustomslidedialog.py
@@ -27,7 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, SpellTextEdit
-from openlp.core.lib.ui import create_save_cancel_button_box
+from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_CustomSlideEditDialog(object):
def setupUi(self, customSlideEditDialog):
@@ -37,7 +37,7 @@ class Ui_CustomSlideEditDialog(object):
self.slideTextEdit = SpellTextEdit(self)
self.slideTextEdit.setObjectName(u'slideTextEdit')
self.dialogLayout.addWidget(self.slideTextEdit)
- self.buttonBox = create_save_cancel_button_box(customSlideEditDialog)
+ self.buttonBox = create_accept_reject_button_box(customSlideEditDialog)
self.splitButton = QtGui.QPushButton(customSlideEditDialog)
self.splitButton.setObjectName(u'splitButton')
self.buttonBox.addButton(self.splitButton,
diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py
index 908c4e18d..c1da5bdfa 100644
--- a/openlp/plugins/custom/lib/mediaitem.py
+++ b/openlp/plugins/custom/lib/mediaitem.py
@@ -28,18 +28,13 @@ import logging
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import MediaManagerItem, BaseListWithDnD, \
- Receiver, ItemCapabilities, translate, check_item_selected
+from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
+ translate, check_item_selected
from openlp.plugins.custom.lib import CustomXMLParser
from openlp.plugins.custom.lib.db import CustomSlide
log = logging.getLogger(__name__)
-class CustomListView(BaseListWithDnD):
- def __init__(self, parent=None):
- self.PluginName = u'Custom'
- BaseListWithDnD.__init__(self, parent)
-
class CustomMediaItem(MediaManagerItem):
"""
This is the custom media manager item for Custom Slides.
@@ -48,9 +43,6 @@ class CustomMediaItem(MediaManagerItem):
def __init__(self, parent, plugin, icon):
self.IconPath = u'custom/custom'
- # this next is a class, not an instance of a class - it will
- # be instanced by the base MediaManagerItem
- self.ListViewWithDnD_class = CustomListView
MediaManagerItem.__init__(self, parent, self, icon)
self.singleServiceItem = False
# Holds information about whether the edit is remotly triggered and
diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py
index 51ef20960..2cc0f1d93 100644
--- a/openlp/plugins/images/imageplugin.py
+++ b/openlp/plugins/images/imageplugin.py
@@ -27,7 +27,6 @@
import logging
from openlp.core.lib import Plugin, StringContent, build_icon, translate
-from openlp.core.lib.ui import UiStrings
from openlp.plugins.images.lib import ImageMediaItem
log = logging.getLogger(__name__)
@@ -36,15 +35,12 @@ class ImagePlugin(Plugin):
log.info(u'Image Plugin loaded')
def __init__(self, plugin_helpers):
- Plugin.__init__(self, u'Images', u'1.9.4', plugin_helpers)
+ Plugin.__init__(self, u'Images', u'1.9.4', plugin_helpers,
+ ImageMediaItem)
self.weight = -7
self.icon_path = u':/plugins/plugin_images.png'
self.icon = build_icon(self.icon_path)
- def getMediaManagerItem(self):
- # Create the MediaManagerItem object.
- return ImageMediaItem(self, self, self.icon)
-
def about(self):
about_text = translate('ImagePlugin', 'Image Plugin'
'
The image plugin provides displaying of images.
One '
@@ -73,4 +69,15 @@ class ImagePlugin(Plugin):
u'title': translate('ImagePlugin', 'Images', 'container title')
}
# Middle Header Bar
- Plugin.setPluginTextStrings(self)
+ tooltips = {
+ u'load': translate('ImagePlugin', 'Load a new Image'),
+ u'import': u'',
+ u'new': translate('ImagePlugin', 'Add a new Image'),
+ u'edit': translate('ImagePlugin', 'Edit the selected Image'),
+ u'delete': translate('ImagePlugin', 'Delete the selected Image'),
+ u'preview': translate('ImagePlugin', 'Preview the selected Image'),
+ u'live': translate('ImagePlugin', 'Send the selected Image live'),
+ u'service': translate('ImagePlugin',
+ 'Add the selected Image to the service')
+ }
+ self.setPluginUiTextStrings(tooltips)
diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py
index 6ec4cf264..5f95a239c 100644
--- a/openlp/plugins/images/lib/mediaitem.py
+++ b/openlp/plugins/images/lib/mediaitem.py
@@ -29,21 +29,14 @@ import os
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \
- ItemCapabilities, SettingsManager, translate, check_item_selected, \
- check_directory_exists, Receiver
+from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
+ SettingsManager, translate, check_item_selected, check_directory_exists, \
+ Receiver
from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.utils import AppLocation, delete_file, get_images_filter
log = logging.getLogger(__name__)
-# We have to explicitly create separate classes for each plugin
-# in order for DnD to the Service manager to work correctly.
-class ImageListView(BaseListWithDnD):
- def __init__(self, parent=None):
- self.PluginName = u'Images'
- BaseListWithDnD.__init__(self, parent)
-
class ImageMediaItem(MediaManagerItem):
"""
This is the custom media manager item for images.
@@ -52,9 +45,6 @@ class ImageMediaItem(MediaManagerItem):
def __init__(self, parent, plugin, icon):
self.IconPath = u'images/image'
- # This next is a class, not an instance of a class - it will
- # be instanced by the base MediaManagerItem.
- self.ListViewWithDnD_class = ImageListView
MediaManagerItem.__init__(self, parent, self, icon)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged)
@@ -64,15 +54,11 @@ class ImageMediaItem(MediaManagerItem):
'Select Image(s)')
file_formats = get_images_filter()
self.OnNewFileMasks = u'%s;;%s (*.*) (*)' % (file_formats,
- unicode(UiStrings.AllFiles))
- self.replaceAction.setText(
- translate('ImagePlugin.MediaItem', 'Replace Background'))
- self.replaceAction.setToolTip(
- translate('ImagePlugin.MediaItem', 'Replace Live Background'))
- self.resetAction.setText(
- translate('ImagePlugin.MediaItem', 'Reset Background'))
- self.resetAction.setToolTip(
- translate('ImagePlugin.MediaItem', 'Reset Live Background'))
+ UiStrings.AllFiles)
+ self.replaceAction.setText(UiStrings.ReplaceBG)
+ self.replaceAction.setToolTip(UiStrings.ReplaceLiveBG)
+ self.resetAction.setText(UiStrings.ResetBG)
+ self.resetAction.setToolTip(UiStrings.ResetLiveBG)
def requiredIcons(self):
MediaManagerItem.requiredIcons(self)
diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py
index f0549a960..cc126bbef 100644
--- a/openlp/plugins/media/lib/mediaitem.py
+++ b/openlp/plugins/media/lib/mediaitem.py
@@ -29,18 +29,13 @@ import os
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \
- ItemCapabilities, SettingsManager, translate, check_item_selected, Receiver
-from openlp.core.lib.ui import critical_error_message_box
+from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
+ SettingsManager, translate, check_item_selected, Receiver
+from openlp.core.lib.ui import UiStrings, critical_error_message_box
+from PyQt4.phonon import Phonon
log = logging.getLogger(__name__)
-class MediaListView(BaseListWithDnD):
- def __init__(self, parent=None):
- self.PluginName = u'Media'
- BaseListWithDnD.__init__(self, parent)
-
-
class MediaMediaItem(MediaManagerItem):
"""
This is the custom media manager item for Media Slides.
@@ -50,30 +45,27 @@ class MediaMediaItem(MediaManagerItem):
def __init__(self, parent, plugin, icon):
self.IconPath = u'images/image'
self.background = False
- # this next is a class, not an instance of a class - it will
- # be instanced by the base MediaManagerItem
- self.ListViewWithDnD_class = MediaListView
self.PreviewFunction = QtGui.QPixmap(
u':/media/media_video.png').toImage()
MediaManagerItem.__init__(self, parent, self, icon)
self.singleServiceItem = False
+ self.mediaObject = Phonon.MediaObject(self)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'video_background_replaced'),
self.videobackgroundReplaced)
+ QtCore.QObject.connect(self.mediaObject,
+ QtCore.SIGNAL(u'stateChanged(Phonon::State, Phonon::State)'),
+ self.videoStart)
def retranslateUi(self):
self.OnNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')
self.OnNewFileMasks = unicode(translate('MediaPlugin.MediaItem',
- 'Videos (%s);;Audio (%s);;All files (*)')) % \
- (self.parent.video_list, self.parent.audio_list)
- self.replaceAction.setText(
- translate('MediaPlugin.MediaItem', 'Replace Background'))
- self.replaceAction.setToolTip(
- translate('MediaPlugin.MediaItem', 'Replace Live Background'))
- self.resetAction.setText(
- translate('MediaPlugin.MediaItem', 'Reset Background'))
- self.resetAction.setToolTip(
- translate('ImagePlugin.MediaItem', 'Reset Live Background'))
+ 'Videos (%s);;Audio (%s);;%s (*)')) % (self.parent.video_list,
+ self.parent.audio_list, UiStrings.AllFiles)
+ self.replaceAction.setText(UiStrings.ReplaceBG)
+ self.replaceAction.setToolTip(UiStrings.ReplaceLiveBG)
+ self.resetAction.setText(UiStrings.ResetBG)
+ self.resetAction.setToolTip(UiStrings.ResetLiveBG)
def requiredIcons(self):
MediaManagerItem.requiredIcons(self)
@@ -133,13 +125,22 @@ class MediaMediaItem(MediaManagerItem):
return False
filename = unicode(item.data(QtCore.Qt.UserRole).toString())
if os.path.exists(filename):
+ self.MediaState = None
+ self.mediaObject.stop()
+ self.mediaObject.clearQueue()
+ self.mediaObject.setCurrentSource(Phonon.MediaSource(filename))
+ self.mediaObject.play()
service_item.title = unicode(
translate('MediaPlugin.MediaItem', 'Media'))
service_item.add_capability(ItemCapabilities.RequiresMedia)
+ service_item.add_capability(ItemCapabilities.AllowsVarableStartTime)
# force a nonexistent theme
service_item.theme = -1
frame = u':/media/image_clapperboard.png'
(path, name) = os.path.split(filename)
+ while not self.MediaState:
+ Receiver.send_message(u'openlp_process_events')
+ service_item.media_length = self.mediaLength
service_item.add_from_command(path, name, frame)
return True
else:
@@ -151,6 +152,7 @@ class MediaMediaItem(MediaManagerItem):
return False
def initialise(self):
+ self.listView.clear()
self.listView.setIconSize(QtCore.QSize(88, 50))
self.loadList(SettingsManager.load_list(self.settingsSection,
self.settingsSection))
@@ -176,3 +178,12 @@ class MediaMediaItem(MediaManagerItem):
item_name.setIcon(build_icon(img))
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
self.listView.addItem(item_name)
+
+ def videoStart(self, newState, oldState):
+ """
+ Start the video at a predetermined point.
+ """
+ if newState == Phonon.PlayingState:
+ self.MediaState = newState
+ self.mediaLength = self.mediaObject.totalTime()/1000
+ self.mediaObject.stop()
diff --git a/openlp/plugins/media/lib/mediatab.py b/openlp/plugins/media/lib/mediatab.py
index 461fbf4ae..c51b53a9a 100644
--- a/openlp/plugins/media/lib/mediatab.py
+++ b/openlp/plugins/media/lib/mediatab.py
@@ -32,8 +32,8 @@ class MediaTab(SettingsTab):
"""
MediaTab is the Media settings tab in the settings dialog.
"""
- def __init__(self, title):
- SettingsTab.__init__(self, title)
+ def __init__(self, title, visible_title):
+ SettingsTab.__init__(self, title, visible_title)
def setupUi(self):
self.setObjectName(u'MediaTab')
@@ -53,9 +53,8 @@ class MediaTab(SettingsTab):
self.onUsePhononCheckBoxChanged)
def retranslateUi(self):
- self.tabTitleVisible = translate('MediaPlugin.MediaTab', 'Media')
- self.mediaModeGroupBox.setTitle(translate('MediaPlugin.MediaTab',
- 'Media Display'))
+ self.mediaModeGroupBox.setTitle(
+ translate('MediaPlugin.MediaTab', 'Media Display'))
self.usePhononCheckBox.setText(
translate('MediaPlugin.MediaTab', 'Use Phonon for video playback'))
diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py
index 1619a07fe..ee413aa8c 100644
--- a/openlp/plugins/media/mediaplugin.py
+++ b/openlp/plugins/media/mediaplugin.py
@@ -30,7 +30,6 @@ import mimetypes
from PyQt4.phonon import Phonon
from openlp.core.lib import Plugin, StringContent, build_icon, translate
-from openlp.core.lib.ui import UiStrings
from openlp.plugins.media.lib import MediaMediaItem, MediaTab
log = logging.getLogger(__name__)
@@ -39,7 +38,8 @@ class MediaPlugin(Plugin):
log.info(u'%s MediaPlugin loaded', __name__)
def __init__(self, plugin_helpers):
- Plugin.__init__(self, u'Media', u'1.9.4', plugin_helpers)
+ Plugin.__init__(self, u'Media', u'1.9.4', plugin_helpers,
+ MediaMediaItem, MediaTab)
self.weight = -6
self.icon_path = u':/plugins/plugin_media.png'
self.icon = build_icon(self.icon_path)
@@ -76,13 +76,6 @@ class MediaPlugin(Plugin):
mimetype = u''
return list, mimetype
- def getSettingsTab(self):
- return MediaTab(self.name)
-
- def getMediaManagerItem(self):
- # Create the MediaManagerItem object.
- return MediaMediaItem(self, self, self.icon)
-
def about(self):
about_text = translate('MediaPlugin', 'Media Plugin'
'
The media plugin provides playback of audio and video.')
@@ -102,4 +95,15 @@ class MediaPlugin(Plugin):
u'title': translate('MediaPlugin', 'Media', 'container title')
}
# Middle Header Bar
- Plugin.setPluginTextStrings(self)
+ tooltips = {
+ u'load': translate('MediaPlugin', 'Load a new Media'),
+ u'import': u'',
+ u'new': translate('MediaPlugin', 'Add a new Media'),
+ u'edit': translate('MediaPlugin', 'Edit the selected Media'),
+ u'delete': translate('MediaPlugin', 'Delete the selected Media'),
+ u'preview': translate('MediaPlugin', 'Preview the selected Media'),
+ u'live': translate('MediaPlugin', 'Send the selected Media live'),
+ u'service': translate('MediaPlugin',
+ 'Add the selected Media to the service')
+ }
+ self.setPluginUiTextStrings(tooltips)
diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py
index 7de095d54..ad5faa2dd 100644
--- a/openlp/plugins/presentations/lib/impresscontroller.py
+++ b/openlp/plugins/presentations/lib/impresscontroller.py
@@ -145,7 +145,12 @@ class ImpressController(PresentationController):
log.debug(u'get COM Desktop OpenOffice')
if not self.manager:
return None
- return self.manager.createInstance(u'com.sun.star.frame.Desktop')
+ desktop = None
+ try:
+ desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
+ except AttributeError:
+ log.exception(u'Failure to find desktop - Impress may have closed')
+ return desktop if desktop else None
def get_com_servicemanager(self):
"""
@@ -166,13 +171,15 @@ class ImpressController(PresentationController):
log.debug(u'Kill OpenOffice')
while self.docs:
self.docs[0].close_presentation()
- if os.name != u'nt':
- desktop = self.get_uno_desktop()
- else:
- desktop = self.get_com_desktop()
- #Sometimes we get a failure and desktop is None
- if not desktop:
+ desktop = None
+ try:
+ if os.name != u'nt':
+ desktop = self.get_uno_desktop()
+ else:
+ desktop = self.get_com_desktop()
+ except:
log.exception(u'Failed to find an OpenOffice desktop to terminate')
+ if not desktop:
return
docs = desktop.getComponents()
if docs.hasElements():
diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py
index 09020692a..0b6ab39cd 100644
--- a/openlp/plugins/presentations/lib/mediaitem.py
+++ b/openlp/plugins/presentations/lib/mediaitem.py
@@ -29,24 +29,13 @@ import os
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \
- SettingsManager, translate, check_item_selected, Receiver, ItemCapabilities
+from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \
+ translate, check_item_selected, Receiver, ItemCapabilities
from openlp.core.lib.ui import critical_error_message_box, media_item_combo_box
from openlp.plugins.presentations.lib import MessageListener
log = logging.getLogger(__name__)
-class PresentationListView(BaseListWithDnD):
- """
- Class for the list of Presentations
-
- We have to explicitly create separate classes for each plugin
- in order for DnD to the Service manager to work correctly.
- """
- def __init__(self, parent=None):
- self.PluginName = u'Presentations'
- BaseListWithDnD.__init__(self, parent)
-
class PresentationMediaItem(MediaManagerItem):
"""
This is the Presentation media manager item for Presentation Items.
@@ -61,9 +50,6 @@ class PresentationMediaItem(MediaManagerItem):
self.controllers = controllers
self.IconPath = u'presentations/presentation'
self.Automatic = u''
- # this next is a class, not an instance of a class - it will
- # be instanced by the base MediaManagerItem
- self.ListViewWithDnD_class = PresentationListView
MediaManagerItem.__init__(self, parent, self, icon)
self.message_listener = MessageListener(self)
QtCore.QObject.connect(Receiver.get_receiver(),
diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py
index fc82600df..fdb66c511 100644
--- a/openlp/plugins/presentations/lib/presentationtab.py
+++ b/openlp/plugins/presentations/lib/presentationtab.py
@@ -27,6 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, SettingsTab, translate
+from openlp.core.lib.ui import UiStrings
class PresentationTab(SettingsTab):
"""
@@ -85,9 +86,7 @@ class PresentationTab(SettingsTab):
checkbox.setText(
unicode(translate('PresentationPlugin.PresentationTab',
'%s (unvailable)')) % controller.name)
- self.AdvancedGroupBox.setTitle(
- translate('PresentationPlugin.PresentationTab',
- 'Advanced'))
+ self.AdvancedGroupBox.setTitle(UiStrings.Advanced)
self.OverrideAppCheckBox.setText(
translate('PresentationPlugin.PresentationTab',
'Allow presentation application to be overriden'))
diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py
index c4cf29aca..ece25e363 100644
--- a/openlp/plugins/presentations/presentationplugin.py
+++ b/openlp/plugins/presentations/presentationplugin.py
@@ -31,7 +31,6 @@ import os
import logging
from openlp.core.lib import Plugin, StringContent, build_icon, translate
-from openlp.core.lib.ui import UiStrings
from openlp.core.utils import AppLocation
from openlp.plugins.presentations.lib import PresentationController, \
PresentationMediaItem, PresentationTab
@@ -168,4 +167,18 @@ class PresentationPlugin(Plugin):
'container title')
}
# Middle Header Bar
- Plugin.setPluginTextStrings(self)
+ tooltips = {
+ u'load': translate('PresentationPlugin', 'Load a new Presentation'),
+ u'import': u'',
+ u'new': u'',
+ u'edit': u'',
+ u'delete': translate('PresentationPlugin',
+ 'Delete the selected Presentation'),
+ u'preview': translate('PresentationPlugin',
+ 'Preview the selected Presentation'),
+ u'live': translate('PresentationPlugin',
+ 'Send the selected Presentation live'),
+ u'service': translate('PresentationPlugin',
+ 'Add the selected Presentation to the service')
+ }
+ self.setPluginUiTextStrings(tooltips)
diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py
index dbc56a61c..b513d4ff7 100644
--- a/openlp/plugins/remotes/remoteplugin.py
+++ b/openlp/plugins/remotes/remoteplugin.py
@@ -38,7 +38,8 @@ class RemotesPlugin(Plugin):
"""
remotes constructor
"""
- Plugin.__init__(self, u'Remotes', u'1.9.4', plugin_helpers)
+ Plugin.__init__(self, u'Remotes', u'1.9.4', plugin_helpers,
+ settingsTabClass=RemoteTab)
self.icon = build_icon(u':/plugins/plugin_remote.png')
self.weight = -1
self.server = None
@@ -61,13 +62,6 @@ class RemotesPlugin(Plugin):
if self.server:
self.server.close()
- def getSettingsTab(self):
- """
- Create the settings Tab
- """
- visible_name = self.getString(StringContent.VisibleName)
- return RemoteTab(self.name, visible_name[u'title'])
-
def about(self):
"""
Information about this plugin
diff --git a/openlp/plugins/songs/forms/__init__.py b/openlp/plugins/songs/forms/__init__.py
index 160a014ac..e75f9fe04 100644
--- a/openlp/plugins/songs/forms/__init__.py
+++ b/openlp/plugins/songs/forms/__init__.py
@@ -57,4 +57,6 @@ from songbookform import SongBookForm
from editverseform import EditVerseForm
from editsongform import EditSongForm
from songmaintenanceform import SongMaintenanceForm
-from songimportform import SongImportForm
\ No newline at end of file
+from songimportform import SongImportForm
+from songexportform import SongExportForm
+
diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py
index 0b3f791d1..09c723364 100644
--- a/openlp/plugins/songs/forms/authorsdialog.py
+++ b/openlp/plugins/songs/forms/authorsdialog.py
@@ -27,7 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
-from openlp.core.lib.ui import create_save_cancel_button_box
+from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_AuthorsDialog(object):
def setupUi(self, authorsDialog):
@@ -57,7 +57,7 @@ class Ui_AuthorsDialog(object):
self.authorLayout.addRow(self.displayLabel, self.displayEdit)
self.dialogLayout.addLayout(self.authorLayout)
self.dialogLayout.addWidget(
- create_save_cancel_button_box(authorsDialog))
+ create_accept_reject_button_box(authorsDialog))
self.retranslateUi(authorsDialog)
authorsDialog.setMaximumHeight(authorsDialog.sizeHint().height())
QtCore.QMetaObject.connectSlotsByName(authorsDialog)
diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py
index 6854a17ae..234d92283 100644
--- a/openlp/plugins/songs/forms/editsongdialog.py
+++ b/openlp/plugins/songs/forms/editsongdialog.py
@@ -27,7 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon, translate
-from openlp.core.lib.ui import UiStrings, create_save_cancel_button_box
+from openlp.core.lib.ui import UiStrings, create_accept_reject_button_box
class Ui_EditSongDialog(object):
def setupUi(self, editSongDialog):
@@ -241,7 +241,7 @@ class Ui_EditSongDialog(object):
self.themeTabLayout.addWidget(self.commentsGroupBox)
self.songTabWidget.addTab(self.themeTab, u'')
self.dialogLayout.addWidget(self.songTabWidget)
- self.buttonBox = create_save_cancel_button_box(editSongDialog)
+ self.buttonBox = create_accept_reject_button_box(editSongDialog)
self.dialogLayout.addWidget(self.buttonBox)
self.retranslateUi(editSongDialog)
QtCore.QMetaObject.connectSlotsByName(editSongDialog)
diff --git a/openlp/plugins/songs/forms/editversedialog.py b/openlp/plugins/songs/forms/editversedialog.py
index b4bc4551f..7caf782e6 100644
--- a/openlp/plugins/songs/forms/editversedialog.py
+++ b/openlp/plugins/songs/forms/editversedialog.py
@@ -27,7 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon, translate, SpellTextEdit
-from openlp.core.lib.ui import create_save_cancel_button_box
+from openlp.core.lib.ui import create_accept_reject_button_box
from openlp.plugins.songs.lib import VerseType
class Ui_EditVerseDialog(object):
@@ -61,7 +61,7 @@ class Ui_EditVerseDialog(object):
self.verseTypeLayout.addStretch()
self.dialogLayout.addLayout(self.verseTypeLayout)
self.dialogLayout.addWidget(
- create_save_cancel_button_box(editVerseDialog))
+ create_accept_reject_button_box(editVerseDialog))
self.retranslateUi(editVerseDialog)
QtCore.QMetaObject.connectSlotsByName(editVerseDialog)
diff --git a/openlp/plugins/songs/forms/songbookdialog.py b/openlp/plugins/songs/forms/songbookdialog.py
index 89b8941b5..f6dd3930c 100644
--- a/openlp/plugins/songs/forms/songbookdialog.py
+++ b/openlp/plugins/songs/forms/songbookdialog.py
@@ -27,7 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
-from openlp.core.lib.ui import create_save_cancel_button_box
+from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_SongBookDialog(object):
def setupUi(self, songBookDialog):
@@ -51,7 +51,7 @@ class Ui_SongBookDialog(object):
self.bookLayout.addRow(self.publisherLabel, self.publisherEdit)
self.dialogLayout.addLayout(self.bookLayout)
self.dialogLayout.addWidget(
- create_save_cancel_button_box(songBookDialog))
+ create_accept_reject_button_box(songBookDialog))
self.retranslateUi(songBookDialog)
songBookDialog.setMaximumHeight(songBookDialog.sizeHint().height())
QtCore.QMetaObject.connectSlotsByName(songBookDialog)
diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py
new file mode 100644
index 000000000..849a1ad1e
--- /dev/null
+++ b/openlp/plugins/songs/forms/songexportform.py
@@ -0,0 +1,367 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
+# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard, Frode Woldsund #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+"""
+The :mod:`songexportform` module provides the wizard for exporting songs to the
+OpenLyrics format.
+"""
+import logging
+
+from PyQt4 import QtCore, QtGui
+
+from openlp.core.lib import build_icon, Receiver, SettingsManager, translate
+from openlp.core.lib.ui import critical_error_message_box
+from openlp.core.ui.wizard import OpenLPWizard
+from openlp.plugins.songs.lib.db import Song
+from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport
+
+log = logging.getLogger(__name__)
+
+class SongExportForm(OpenLPWizard):
+ """
+ This is the Song Export Wizard, which allows easy exporting of Songs to the
+ OpenLyrics format.
+ """
+ log.info(u'SongExportForm loaded')
+
+ def __init__(self, parent, plugin):
+ """
+ Instantiate the wizard, and run any extra setup we need to.
+
+ ``parent``
+ The QWidget-derived parent of the wizard.
+
+ ``plugin``
+ The songs plugin.
+ """
+ self.plugin = plugin
+ OpenLPWizard.__init__(self, parent, plugin, u'songExportWizard',
+ u':/wizards/wizard_exportsong.bmp')
+ self.stop_export_flag = False
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_export)
+
+ def stop_export(self):
+ """
+ Sets the flag for the exporter to stop the export.
+ """
+ log.debug(u'Stopping songs export')
+ self.stop_export_flag = True
+
+ def setupUi(self, image):
+ """
+ Set up the song wizard UI.
+ """
+ OpenLPWizard.setupUi(self, image)
+
+ def customInit(self):
+ """
+ Song wizard specific initialisation.
+ """
+ pass
+
+ def customSignals(self):
+ """
+ Song wizard specific signals.
+ """
+ QtCore.QObject.connect(self.availableListWidget,
+ QtCore.SIGNAL(u'itemActivated(QListWidgetItem*)'),
+ self.onItemPressed)
+ QtCore.QObject.connect(self.searchLineEdit,
+ QtCore.SIGNAL(u'textEdited(const QString&)'),
+ self.onSearchLineEditChanged)
+ QtCore.QObject.connect(self.uncheckButton,
+ QtCore.SIGNAL(u'clicked()'), self.onUncheckButtonClicked)
+ QtCore.QObject.connect(self.checkButton,
+ QtCore.SIGNAL(u'clicked()'), self.onCheckButtonClicked)
+ QtCore.QObject.connect(self.directoryButton,
+ QtCore.SIGNAL(u'clicked()'), self.onDirectoryButtonClicked)
+
+ def addCustomPages(self):
+ """
+ Add song wizard specific pages.
+ """
+ # The page with all available songs.
+ self.availableSongsPage = QtGui.QWizardPage()
+ self.availableSongsPage.setObjectName(u'availableSongsPage')
+ self.availableSongsLayout = QtGui.QHBoxLayout(self.availableSongsPage)
+ self.availableSongsLayout.setObjectName(u'availableSongsLayout')
+ self.verticalLayout = QtGui.QVBoxLayout()
+ self.verticalLayout.setObjectName(u'verticalLayout')
+ self.availableListWidget = QtGui.QListWidget(self.availableSongsPage)
+ self.availableListWidget.setObjectName(u'availableListWidget')
+ self.verticalLayout.addWidget(self.availableListWidget)
+ self.horizontalLayout = QtGui.QHBoxLayout()
+ self.horizontalLayout.setObjectName(u'horizontalLayout')
+ self.searchLabel = QtGui.QLabel(self.availableSongsPage)
+ self.searchLabel.setObjectName(u'searchLabel')
+ self.horizontalLayout.addWidget(self.searchLabel)
+ self.searchLineEdit = QtGui.QLineEdit(self.availableSongsPage)
+ self.searchLineEdit.setObjectName(u'searchLineEdit')
+ self.horizontalLayout.addWidget(self.searchLineEdit)
+ spacerItem = QtGui.QSpacerItem(40, 20,
+ QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem)
+ self.uncheckButton = QtGui.QPushButton(self.availableSongsPage)
+ self.uncheckButton.setObjectName(u'uncheckButton')
+ self.horizontalLayout.addWidget(self.uncheckButton)
+ self.checkButton = QtGui.QPushButton(self.availableSongsPage)
+ self.checkButton.setObjectName(u'selectButton')
+ self.horizontalLayout.addWidget(self.checkButton)
+ self.verticalLayout.addLayout(self.horizontalLayout)
+ self.availableSongsLayout.addLayout(self.verticalLayout)
+ self.addPage(self.availableSongsPage)
+ # The page with the selected songs.
+ self.exportSongPage = QtGui.QWizardPage()
+ self.exportSongPage.setObjectName(u'availableSongsPage')
+ self.exportSongLayout = QtGui.QHBoxLayout(self.exportSongPage)
+ self.exportSongLayout.setObjectName(u'exportSongLayout')
+ self.gridLayout = QtGui.QGridLayout()
+ self.gridLayout.setObjectName(u'gridLayout')
+ self.selectedListWidget = QtGui.QListWidget(self.exportSongPage)
+ self.selectedListWidget.setObjectName(u'selectedListWidget')
+ self.gridLayout.addWidget(self.selectedListWidget, 1, 0, 1, 1)
+ self.horizontalLayout = QtGui.QHBoxLayout()
+ self.horizontalLayout.setObjectName(u'horizontalLayout')
+ self.directoryLabel = QtGui.QLabel(self.exportSongPage)
+ self.directoryLabel.setObjectName(u'directoryLabel')
+ self.horizontalLayout.addWidget(self.directoryLabel)
+ self.directoryLineEdit = QtGui.QLineEdit(self.exportSongPage)
+ self.directoryLineEdit.setObjectName(u'directoryLineEdit')
+ self.horizontalLayout.addWidget(self.directoryLineEdit)
+ self.directoryButton = QtGui.QToolButton(self.exportSongPage)
+ self.directoryButton.setIcon(build_icon(u':/exports/export_load.png'))
+ self.directoryButton.setObjectName(u'directoryButton')
+ self.horizontalLayout.addWidget(self.directoryButton)
+ self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
+ self.exportSongLayout.addLayout(self.gridLayout)
+ self.addPage(self.exportSongPage)
+
+ def retranslateUi(self):
+ """
+ Song wizard localisation.
+ """
+ self.setWindowTitle(
+ translate('SongsPlugin.ExportWizardForm', 'Song Export Wizard'))
+ self.titleLabel.setText(
+ u'%s' %
+ translate('SongsPlugin.ExportWizardForm',
+ 'Welcome to the Song Export Wizard'))
+ self.informationLabel.setText(
+ translate('SongsPlugin.ExportWizardForm', 'This wizard will help to'
+ ' export your songs to the open and free OpenLyrics worship song '
+ 'format.'))
+ self.availableSongsPage.setTitle(
+ translate('SongsPlugin.ExportWizardForm', 'Select Songs'))
+ self.availableSongsPage.setSubTitle(
+ translate('SongsPlugin.ExportWizardForm',
+ 'Check the songs, you want to export.'))
+ self.searchLabel.setText(
+ translate('SongsPlugin.ExportWizardForm', 'Search:'))
+ self.uncheckButton.setText(
+ translate('SongsPlugin.ExportWizardForm', 'Uncheck All'))
+ self.checkButton.setText(
+ translate('SongsPlugin.ExportWizardForm', 'Check All'))
+ self.exportSongPage.setTitle(
+ translate('SongsPlugin.ExportWizardForm', 'Select Directory'))
+ self.exportSongPage.setSubTitle(
+ translate('SongsPlugin.ExportWizardForm',
+ 'Select the directory you want the songs to be saved.'))
+ self.directoryLabel.setText(
+ translate('SongsPlugin.ExportWizardForm', 'Directory:'))
+ self.progressPage.setTitle(
+ translate('SongsPlugin.ExportWizardForm', 'Exporting'))
+ self.progressPage.setSubTitle(
+ translate('SongsPlugin.ExportWizardForm',
+ 'Please wait while your songs are exported.'))
+ self.progressLabel.setText(
+ translate('SongsPlugin.ExportWizardForm', 'Ready.'))
+ self.progressBar.setFormat(
+ translate('SongsPlugin.ExportWizardForm', '%p%'))
+
+ def validateCurrentPage(self):
+ """
+ Validate the current page before moving on to the next page.
+ """
+ if self.currentPage() == self.welcomePage:
+ return True
+ elif self.currentPage() == self.availableSongsPage:
+ items = [
+ item for item in self._findListWidgetItems(
+ self.availableListWidget) if item.checkState()
+ ]
+ if not items:
+ critical_error_message_box(
+ translate('SongsPlugin.ExportWizardForm',
+ 'No Song Selected'),
+ translate('SongsPlugin.ExportWizardForm',
+ 'You need to add at least one Song to export.'))
+ return False
+ self.selectedListWidget.clear()
+ # Add the songs to the list of selected songs.
+ for item in items:
+ song = QtGui.QListWidgetItem(item.text())
+ song.setData(QtCore.Qt.UserRole,
+ QtCore.QVariant(item.data(QtCore.Qt.UserRole).toPyObject()))
+ song.setFlags(QtCore.Qt.ItemIsEnabled)
+ self.selectedListWidget.addItem(song)
+ return True
+ elif self.currentPage() == self.exportSongPage:
+ if not self.directoryLineEdit.text():
+ critical_error_message_box(
+ translate('SongsPlugin.ExportWizardForm',
+ 'No Save Location specified'),
+ translate('SongsPlugin.ExportWizardForm',
+ 'You need to specified a directory to save the songs in.'))
+ return False
+ return True
+ elif self.currentPage() == self.progressPage:
+ self.availableListWidget.clear()
+ self.selectedListWidget.clear()
+ return True
+
+ def setDefaults(self):
+ """
+ Set default form values for the song export wizard.
+ """
+ self.restart()
+ self.finishButton.setVisible(False)
+ self.cancelButton.setVisible(True)
+ self.availableListWidget.clear()
+ self.selectedListWidget.clear()
+ self.directoryLineEdit.clear()
+ # Load the list of songs.
+ Receiver.send_message(u'cursor_busy')
+ songs = self.plugin.manager.get_all_objects(Song)
+ for song in songs:
+ authors = u', '.join([author.display_name
+ for author in song.authors])
+ title = u'%s (%s)' % (unicode(song.title), authors)
+ item = QtGui.QListWidgetItem(title)
+ item.setData(QtCore.Qt.UserRole, QtCore.QVariant(song))
+ item.setFlags(QtCore.Qt.ItemIsSelectable|
+ QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
+ item.setCheckState(QtCore.Qt.Unchecked)
+ self.availableListWidget.addItem(item)
+ Receiver.send_message(u'cursor_normal')
+
+ def preWizard(self):
+ """
+ Perform pre export tasks.
+ """
+ OpenLPWizard.preWizard(self)
+ self.progressLabel.setText(
+ translate('SongsPlugin.ExportWizardForm', 'Starting export...'))
+ Receiver.send_message(u'openlp_process_events')
+
+ def performWizard(self):
+ """
+ Perform the actual export. This creates an *openlyricsexport* instance
+ and calls the *do_export* method.
+ """
+ songs = [
+ song.data(QtCore.Qt.UserRole).toPyObject()
+ for song in self._findListWidgetItems(self.selectedListWidget)
+ ]
+ exporter = OpenLyricsExport(
+ self, songs, unicode(self.directoryLineEdit.text()))
+ if exporter.do_export():
+ self.progressLabel.setText(
+ translate('SongsPlugin.SongExportForm', 'Finished export.'))
+ else:
+ self.progressLabel.setText(
+ translate('SongsPlugin.SongExportForm',
+ 'Your song export failed.'))
+
+ def _findListWidgetItems(self, listWidget, text=u''):
+ """
+ Returns a list of *QListWidgetItem*s of the ``listWidget``. Note, that
+ hidden items are included.
+
+ ``listWidget``
+ The widget to get all items from. (QListWidget)
+
+ ``text``
+ The text to search for. (unicode string)
+ """
+ return [item for item in listWidget.findItems(
+ QtCore.QString(unicode(text)), QtCore.Qt.MatchContains)
+ ]
+
+ def onItemPressed(self, item):
+ """
+ Called, when an item in the *availableListWidget* has been pressed. Thes
+ item is check if it was not checked, whereas it is unchecked when it was
+ checked.
+
+ ``item``
+ The *QListWidgetItem* which was pressed.
+ """
+ item.setCheckState(
+ QtCore.Qt.Unchecked if item.checkState() else QtCore.Qt.Checked)
+
+ def onSearchLineEditChanged(self, text):
+ """
+ The *searchLineEdit*'s text has been changed. Update the list of
+ available songs. Note that any song, which does not match the ``text``
+ will be hidden, but not unchecked!
+
+ ``text``
+ The text of the *searchLineEdit*. (QString)
+ """
+ search_result = [
+ song for song in self._findListWidgetItems(
+ self.availableListWidget, unicode(text))
+ ]
+ for item in self._findListWidgetItems(self.availableListWidget):
+ item.setHidden(False if item in search_result else True)
+
+ def onUncheckButtonClicked(self):
+ """
+ The *uncheckButton* has been clicked. Set all songs unchecked.
+ """
+ for row in range(self.availableListWidget.count()):
+ item = self.availableListWidget.item(row)
+ item.setCheckState(QtCore.Qt.Unchecked)
+
+ def onCheckButtonClicked(self):
+ """
+ The *checkButton* has been clicked. Set all songs checked.
+ """
+ for row in range(self.availableListWidget.count()):
+ item = self.availableListWidget.item(row)
+ item.setCheckState(QtCore.Qt.Checked)
+
+ def onDirectoryButtonClicked(self):
+ """
+ Called when the *directoryButton* was clicked. Opens a dialog and writes
+ the path to *directoryLineEdit*.
+ """
+ path = unicode(QtGui.QFileDialog.getExistingDirectory(self,
+ translate('SongsPlugin.ExportWizardForm', 'Selecte to Folder'),
+ SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
+ options=QtGui.QFileDialog.ShowDirsOnly))
+ SettingsManager.set_last_dir(self.plugin.settingsSection, path, 1)
+ self.directoryLineEdit.setText(path)
diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py
index 8cd8c70fa..6e2a45b45 100644
--- a/openlp/plugins/songs/forms/songimportform.py
+++ b/openlp/plugins/songs/forms/songimportform.py
@@ -140,6 +140,12 @@ class SongImportForm(OpenLPWizard):
QtCore.QObject.connect(self.songBeamerRemoveButton,
QtCore.SIGNAL(u'clicked()'),
self.onSongBeamerRemoveButtonClicked)
+ QtCore.QObject.connect(self.songShowPlusAddButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onSongShowPlusAddButtonClicked)
+ QtCore.QObject.connect(self.songShowPlusRemoveButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onSongShowPlusRemoveButtonClicked)
def addCustomPages(self):
"""
@@ -188,6 +194,8 @@ class SongImportForm(OpenLPWizard):
self.addFileSelectItem(u'ew', single_select=True)
# Words of Worship
self.addFileSelectItem(u'songBeamer')
+ # Song Show Plus
+ self.addFileSelectItem(u'songShowPlus')
# Commented out for future use.
# self.addFileSelectItem(u'csv', u'CSV', single_select=True)
self.sourceLayout.addLayout(self.formatStack)
@@ -237,6 +245,8 @@ class SongImportForm(OpenLPWizard):
translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
self.formatComboBox.setItemText(10,
translate('SongsPlugin.ImportWizardForm', 'SongBeamer'))
+ self.formatComboBox.setItemText(11,
+ translate('SongsPlugin.ImportWizardForm', 'SongShow Plus'))
# self.formatComboBox.setItemText(11,
# translate('SongsPlugin.ImportWizardForm', 'CSV'))
self.openLP2FilenameLabel.setText(
@@ -301,6 +311,10 @@ class SongImportForm(OpenLPWizard):
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
self.songBeamerRemoveButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
+ self.songShowPlusAddButton.setText(
+ translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
+ self.songShowPlusRemoveButton.setText(
+ translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
# self.csvFilenameLabel.setText(
# translate('SongsPlugin.ImportWizardForm', 'Filename:'))
# self.csvBrowseButton.setText(
@@ -438,38 +452,20 @@ class SongImportForm(OpenLPWizard):
'file to import from.'))
self.songBeamerAddButton.setFocus()
return False
+ elif source_format == SongFormat.SongShowPlus:
+ if self.songShowPlusFileListWidget.count() == 0:
+ critical_error_message_box(
+ translate('SongsPlugin.ImportWizardForm',
+ 'No SongShow Plus Files Selected'),
+ translate('SongsPlugin.ImportWizardForm',
+ 'You need to add at least one SongShow Plus '
+ 'file to import from.'))
+ self.wordsOfWorshipAddButton.setFocus()
+ return False
return True
elif self.currentPage() == self.progressPage:
return True
- def getFileName(self, title, editbox, filters=u''):
- """
- Opens a QFileDialog and writes the filename to the given editbox.
-
- ``title``
- The title of the dialog (unicode).
-
- ``editbox``
- A editbox (QLineEdit).
-
- ``filters``
- The file extension filters. It should contain the file descriptions
- as well as the file extensions. For example::
-
- u'OpenLP 2.0 Databases (*.sqlite)'
- """
- if filters:
- filters += u';;'
- filters += u'%s (*)' % translate('SongsPlugin.ImportWizardForm',
- 'All Files')
- filename = QtGui.QFileDialog.getOpenFileName(self, title,
- SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
- filters)
- if filename:
- editbox.setText(filename)
- SettingsManager.set_last_dir(self.plugin.settingsSection,
- os.path.split(unicode(filename))[0], 1)
-
def getFiles(self, title, listbox, filters=u''):
"""
Opens a QFileDialog and writes the filenames to the given listbox.
@@ -671,12 +667,24 @@ class SongImportForm(OpenLPWizard):
Remove selected SongBeamer files from the import list
"""
self.removeSelectedItems(self.songBeamerFileListWidget)
+
+ def onSongShowPlusAddButtonClicked(self):
+ """
+ Get SongShow Plus song database files
+ """
+ self.getFiles(
+ translate('SongsPlugin.ImportWizardForm',
+ 'Select SongShow Plus Files'),
+ self.songShowPlusFileListWidget, u'%s (*.sbsong)'
+ % translate('SongsPlugin.ImportWizardForm',
+ 'SongShow Plus Song Files')
+ )
- def registerFields(self):
+ def onSongShowPlusRemoveButtonClicked(self):
"""
- Register song import wizard fields.
+ Remove selected SongShow Plus files from the import list
"""
- pass
+ self.removeSelectedItems(self.songShowPlusFileListWidget)
def setDefaults(self):
"""
@@ -697,6 +705,7 @@ class SongImportForm(OpenLPWizard):
self.easiSlidesFilenameEdit.setText(u'')
self.ewFilenameEdit.setText(u'')
self.songBeamerFileListWidget.clear()
+ self.songShowPlusFileListWidget.clear()
#self.csvFilenameEdit.setText(u'')
def preWizard(self):
@@ -773,6 +782,12 @@ class SongImportForm(OpenLPWizard):
importer = self.plugin.importSongs(SongFormat.SongBeamer,
filenames=self.getListOfFiles(self.songBeamerFileListWidget)
)
+ elif source_format == SongFormat.SongShowPlus:
+ # Import ShongShow Plus songs
+ importer = self.plugin.importSongs(SongFormat.SongShowPlus,
+ filenames=self.getListOfFiles(
+ self.songShowPlusFileListWidget)
+ )
if importer.do_import():
self.progressLabel.setText(
translate('SongsPlugin.SongImportForm', 'Finished import.'))
diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py
index 596597034..1e7bdb6a0 100644
--- a/openlp/plugins/songs/forms/topicsdialog.py
+++ b/openlp/plugins/songs/forms/topicsdialog.py
@@ -27,7 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
-from openlp.core.lib.ui import create_save_cancel_button_box
+from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_TopicsDialog(object):
def setupUi(self, topicsDialog):
@@ -45,7 +45,7 @@ class Ui_TopicsDialog(object):
self.nameLayout.addRow(self.nameLabel, self.nameEdit)
self.dialogLayout.addLayout(self.nameLayout)
self.dialogLayout.addWidget(
- create_save_cancel_button_box(topicsDialog))
+ create_accept_reject_button_box(topicsDialog))
self.retranslateUi(topicsDialog)
topicsDialog.setMaximumHeight(topicsDialog.sizeHint().height())
QtCore.QMetaObject.connectSlotsByName(topicsDialog)
diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py
index 6f566ff4f..cbe5c6922 100644
--- a/openlp/plugins/songs/lib/importer.py
+++ b/openlp/plugins/songs/lib/importer.py
@@ -34,6 +34,7 @@ from wowimport import WowImport
from cclifileimport import CCLIFileImport
from ewimport import EasyWorshipSongImport
from songbeamerimport import SongBeamerImport
+from songshowplusimport import SongShowPlusImport
# Imports that might fail
try:
from olp1import import OpenLP1SongImport
@@ -71,6 +72,7 @@ class SongFormat(object):
EasiSlides = 8
EasyWorship = 9
SongBeamer = 10
+ SongShowPlus = 11
@staticmethod
def get_class(format):
@@ -102,6 +104,8 @@ class SongFormat(object):
return EasyWorshipSongImport
elif format == SongFormat.SongBeamer:
return SongBeamerImport
+ elif format == SongFormat.SongShowPlus:
+ return SongShowPlusImport
return None
@staticmethod
@@ -120,7 +124,8 @@ class SongFormat(object):
SongFormat.Generic,
SongFormat.EasiSlides,
SongFormat.EasyWorship,
- SongFormat.SongBeamer
+ SongFormat.SongBeamer,
+ SongFormat.SongShowPlus
]
@staticmethod
diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py
index 312d0d6e7..283aa6c03 100644
--- a/openlp/plugins/songs/lib/mediaitem.py
+++ b/openlp/plugins/songs/lib/mediaitem.py
@@ -31,23 +31,17 @@ import re
from PyQt4 import QtCore, QtGui
from sqlalchemy.sql import or_
-from openlp.core.lib import MediaManagerItem, BaseListWithDnD, Receiver, \
- ItemCapabilities, translate, check_item_selected, PluginStatus
+from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
+ translate, check_item_selected, PluginStatus
from openlp.core.lib.ui import UiStrings
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
- SongImportForm
+ SongImportForm, SongExportForm
from openlp.plugins.songs.lib import OpenLyrics, SongXML
from openlp.plugins.songs.lib.db import Author, Song
from openlp.core.lib.searchedit import SearchEdit
log = logging.getLogger(__name__)
-class SongListView(BaseListWithDnD):
- def __init__(self, parent=None):
- self.PluginName = u'Songs'
- BaseListWithDnD.__init__(self, parent)
-
-
class SongMediaItem(MediaManagerItem):
"""
This is the custom media manager item for Songs.
@@ -56,7 +50,6 @@ class SongMediaItem(MediaManagerItem):
def __init__(self, parent, plugin, icon):
self.IconPath = u'songs/song'
- self.ListViewWithDnD_class = SongListView
MediaManagerItem.__init__(self, parent, self, icon)
self.edit_song_form = EditSongForm(self, self.parent.manager)
self.openLyrics = OpenLyrics(self.parent.manager)
@@ -265,6 +258,11 @@ class SongMediaItem(MediaManagerItem):
if self.import_wizard.exec_() == QtGui.QDialog.Accepted:
Receiver.send_message(u'songs_load_list')
+ def onExportClick(self):
+ if not hasattr(self, u'export_wizard'):
+ self.export_wizard = SongExportForm(self, self.parent)
+ self.export_wizard.exec_()
+
def onNewClick(self):
log.debug(u'onNewClick')
self.edit_song_form.newSong()
diff --git a/openlp/plugins/songs/lib/openlyricsexport.py b/openlp/plugins/songs/lib/openlyricsexport.py
new file mode 100755
index 000000000..ffb1a2d6f
--- /dev/null
+++ b/openlp/plugins/songs/lib/openlyricsexport.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
+# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard, Frode Woldsund #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+"""
+The :mod:`openlyricsexport` module provides the functionality for exporting
+songs from the database to the OpenLyrics format.
+"""
+import logging
+import os
+
+from lxml import etree
+
+from openlp.core.lib import Receiver, translate
+from openlp.plugins.songs.lib import OpenLyrics
+
+log = logging.getLogger(__name__)
+
+class OpenLyricsExport(object):
+ """
+ This provides the Openlyrics export.
+ """
+ def __init__(self, parent, songs, save_path):
+ """
+ Initialise the export.
+ """
+ log.debug(u'initialise OpenLyricsExport')
+ self.parent = parent
+ self.manager = parent.plugin.manager
+ self.songs = songs
+ self.save_path = save_path
+ if not os.path.exists(self.save_path):
+ os.mkdir(self.save_path)
+
+ def do_export(self):
+ """
+ Export the songs.
+ """
+ log.debug(u'started OpenLyricsExport')
+ openLyrics = OpenLyrics(self.manager)
+ self.parent.progressBar.setMaximum(len(self.songs))
+ for song in self.songs:
+ Receiver.send_message(u'openlp_process_events')
+ if self.parent.stop_export_flag:
+ return False
+ self.parent.incrementProgressBar(unicode(translate(
+ 'SongsPlugin.OpenLyricsExport', 'Exporting "%s"...')) %
+ song.title)
+ xml = openLyrics.song_to_xml(song)
+ tree = etree.ElementTree(etree.fromstring(xml))
+ tree.write(os.path.join(self.save_path, song.title + u'.xml'),
+ encoding=u'utf-8', xml_declaration=True, pretty_print=True)
+ return True
diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py
index e7557f952..8c6d283e3 100644
--- a/openlp/plugins/songs/lib/opensongimport.py
+++ b/openlp/plugins/songs/lib/opensongimport.py
@@ -36,6 +36,7 @@ from openlp.plugins.songs.lib.songimport import SongImport
log = logging.getLogger(__name__)
+#TODO: Use lxml for parsing and make sure we use methods of "SongImport" .
class OpenSongImport(SongImport):
"""
Import songs exported from OpenSong
@@ -146,7 +147,7 @@ class OpenSongImport(SongImport):
log.info(u'Zip importing %s', parts[-1])
self.import_wizard.incrementProgressBar(
unicode(translate('SongsPlugin.ImportWizardForm',
- 'Importing %s...')) % parts[-1])
+ 'Importing %s...')) % parts[-1])
songfile = z.open(song)
self.do_import_file(songfile)
if self.commit:
@@ -276,7 +277,7 @@ class OpenSongImport(SongImport):
for num in versenums:
versetag = u'%s%s' % (our_verse_type, num)
lines = u'\n'.join(verses[versetype][num])
- self.verses.append([versetag, lines])
+ self.add_verse(lines, versetag)
# Keep track of what we have for error checking later
versetags[versetag] = 1
# now figure out the presentation order
@@ -292,6 +293,8 @@ class OpenSongImport(SongImport):
else:
log.warn(u'No verse order available for %s, skipping.',
self.title)
+ # TODO: make sure that the default order list will be overwritten, if
+ # the songs provides its own order list.
for tag in order:
if tag[0].isdigit():
# Assume it's a verse if it has no prefix
diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py
new file mode 100644
index 000000000..78c2e838d
--- /dev/null
+++ b/openlp/plugins/songs/lib/songshowplusimport.py
@@ -0,0 +1,212 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
+# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard, Frode Woldsund #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+"""
+The :mod:`wowimport` module provides the functionality for importing Words of
+Worship songs into the OpenLP database.
+"""
+import os
+import logging
+import struct
+
+from openlp.plugins.songs.lib.songimport import SongImport
+
+TITLE = 1
+AUTHOR = 2
+COPYRIGHT = 3
+CCLI_NO = 5
+VERSE = 12
+CHORUS = 20
+TOPIC = 29
+COMMENTS = 30
+VERSE_ORDER = 31
+SONG_BOOK = 35
+SONG_NUMBER = 36
+CUSTOM_VERSE = 37
+
+log = logging.getLogger(__name__)
+
+class SongShowPlusImport(SongImport):
+ """
+ The :class:`SongShowPlusImport` class provides the ability to import song
+ files from SongShow Plus.
+
+ **SongShow Plus Song File Format:**
+
+ The SongShow Plus song file format is as follows:
+
+ * Each piece of data in the song file has some information that precedes
+ it.
+ * The general format of this data is as follows:
+ 4 Bytes, forming a 32 bit number, a key if you will, this describes what
+ the data is (see blockKey below)
+ 4 Bytes, forming a 32 bit number, which is the number of bytes until the
+ next block starts
+ 1 Byte, which tells how namy bytes follows
+ 1 or 4 Bytes, describes how long the string is, if its 1 byte, the string
+ is less than 255
+ The next bytes are the actuall data.
+ The next block of data follows on.
+
+ This description does differ for verses. Which includes extra bytes
+ stating the verse type or number. In some cases a "custom" verse is used,
+ in that case, this block will in include 2 strings, with the associated
+ string length descriptors. The first string is the name of the verse, the
+ second is the verse content.
+
+ The file is ended with four null bytes.
+
+ Valid extensions for a SongShow Plus song file are:
+
+ * .sbsong
+ """
+ otherList = {}
+ otherCount = 0
+
+ def __init__(self, master_manager, **kwargs):
+ """
+ Initialise the import.
+
+ ``master_manager``
+ The song manager for the running OpenLP installation.
+ """
+ SongImport.__init__(self, master_manager)
+ if kwargs.has_key(u'filename'):
+ self.import_source = kwargs[u'filename']
+ if kwargs.has_key(u'filenames'):
+ self.import_source = kwargs[u'filenames']
+ log.debug(self.import_source)
+
+ def do_import(self):
+ """
+ Receive a single file or a list of files to import.
+ """
+ if isinstance(self.import_source, list):
+ self.import_wizard.progressBar.setMaximum(len(self.import_source))
+ for file in self.import_source:
+ author = u''
+ copyright = u''
+ self.sspVerseOrderList = []
+ otherCount = 0
+ otherList = {}
+ file_name = os.path.split(file)[1]
+ self.import_wizard.incrementProgressBar(
+ u'Importing %s' % (file_name), 0)
+ songData = open(file, 'rb')
+ while (1):
+ blockKey, = struct.unpack("I",songData.read(4))
+ # The file ends with 4 NUL's
+ if blockKey == 0:
+ break
+ nextBlockStarts, = struct.unpack("I",songData.read(4))
+ if blockKey == VERSE or blockKey == CHORUS:
+ null, verseNo, = struct.unpack("BB",songData.read(2))
+ elif blockKey == CUSTOM_VERSE:
+ null, verseNameLength, = struct.unpack("BB",
+ songData.read(2))
+ verseName = songData.read(verseNameLength)
+ lengthDescriptorSize, = struct.unpack("B",songData.read(1))
+ # Detect if/how long the length descriptor is
+ if lengthDescriptorSize == 12:
+ lengthDescriptor, = struct.unpack("I",songData.read(4))
+ elif lengthDescriptorSize == 2:
+ lengthDescriptor = 1
+ elif lengthDescriptorSize == 9:
+ lengthDescriptor = 0
+ else:
+ lengthDescriptor, = struct.unpack("B",songData.read(1))
+ data = songData.read(lengthDescriptor)
+
+ if blockKey == TITLE:
+ self.title = unicode(data, u'cp1252')
+ elif blockKey == AUTHOR:
+ authors = data.split(" / ")
+ for author in authors:
+ if author.find(",") !=-1:
+ authorParts = author.split(", ")
+ author = authorParts[1] + " " + authorParts[0]
+ self.parse_author(unicode(author, u'cp1252'))
+ elif blockKey == COPYRIGHT:
+ self.add_copyright(unicode(data, u'cp1252'))
+ elif blockKey == CCLI_NO:
+ self.ccli_number = int(data)
+ elif blockKey == VERSE:
+ self.add_verse(unicode(data, u'cp1252'),
+ "V%s" % verseNo)
+ elif blockKey == CHORUS:
+ self.add_verse(unicode(data, u'cp1252'),
+ "C%s" % verseNo)
+ elif blockKey == TOPIC:
+ self.topics.append(unicode(data, u'cp1252'))
+ elif blockKey == COMMENTS:
+ self.comments = unicode(data, u'cp1252')
+ elif blockKey == VERSE_ORDER:
+ verseTag = self.toOpenLPVerseTag(data)
+ self.sspVerseOrderList.append(unicode(verseTag,
+ u'cp1252'))
+ elif blockKey == SONG_BOOK:
+ self.song_book_name = unicode(data, u'cp1252')
+ elif blockKey == SONG_NUMBER:
+ self.song_number = ord(data)
+ elif blockKey == CUSTOM_VERSE:
+ verseTag = self.toOpenLPVerseTag(verseName)
+ self.add_verse(unicode(data, u'cp1252'), verseTag)
+ else:
+ log.debug("Unrecognised blockKey: %s, data: %s"
+ %(blockKey, data))
+ self.verse_order_list = self.sspVerseOrderList
+ songData.close()
+ self.finish()
+ self.import_wizard.incrementProgressBar(
+ u'Importing %s' % (file_name))
+ return True
+
+ def toOpenLPVerseTag(self, verseName):
+ if verseName.find(" ")!=-1:
+ verseParts = verseName.split(" ")
+ verseType = verseParts[0]
+ verseNumber = verseParts[1]
+ else:
+ verseType = verseName
+ verseNumber = "1"
+ verseType = verseType.lower()
+ if verseType == "verse":
+ verseTag = "V"
+ elif verseType == "chorus":
+ verseTag = "C"
+ elif verseType == "bridge":
+ verseTag = "B"
+ elif verseType == "pre-chorus":
+ verseTag = "P"
+ elif verseType == "bridge":
+ verseTag = "B"
+ else:
+ if not self.otherList.has_key(verseName):
+ self.otherCount = self.otherCount + 1
+ self.otherList[verseName] = str(self.otherCount)
+ verseTag = "O"
+ verseNumber = self.otherList[verseName]
+ verseTag = verseTag + verseNumber
+ return verseTag
diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py
index 4bf11887a..b96e79961 100644
--- a/openlp/plugins/songs/lib/xml.py
+++ b/openlp/plugins/songs/lib/xml.py
@@ -60,6 +60,7 @@ The XML of an `OpenLyrics `_ song looks like this::
"""
+import datetime
import logging
import re
@@ -89,8 +90,10 @@ class SongXML(object):
Add a verse to the ```` tag.
``type``
- A string denoting the type of verse. Possible values are "V",
- "C", "B", "P", "I", "E" and "O".
+ A string denoting the type of verse. Possible values are *Verse*,
+ *Chorus*, *Bridge*, *Pre-Chorus*, *Intro*, *Ending* and *Other*.
+ Any other type is **not** allowed, this also includes translated
+ types.
``number``
An integer denoting the number of the item, for example: verse 1.
@@ -126,8 +129,8 @@ class SongXML(object):
The returned list has the following format::
- [[{'lang': 'en', 'type': 'V', 'label': '1'}, u"The English verse."],
- [{'lang': 'en', 'type': 'C', 'label': '1'}, u"The English chorus."]]
+ [[{'lang': 'en', 'type': 'Verse', 'label': '1'}, u"English verse"],
+ [{'lang': 'en', 'type': 'Chorus', 'label': '1'}, u"English chorus"]]
"""
self.song_xml = None
if xml[:5] == u'``
- The attribute *translit* is not supported.
+ The attribute *translit* is not supported. Note, the attribute *lang* is
+ considered, but there is not further functionality implemented yet.
````
OpenLP supports this property.
"""
+ IMPLEMENTED_VERSION = u'0.7'
def __init__(self, manager):
self.manager = manager
@@ -222,8 +227,14 @@ class OpenLyrics(object):
"""
sxml = SongXML()
verse_list = sxml.get_verses(song.lyrics)
- song_xml = objectify.fromstring(
- u'')
+ song_xml = objectify.fromstring(u'')
+ # Append the necessary meta data to the song.
+ song_xml.set(u'xmlns', u'http://openlyrics.info/namespace/2009/song')
+ song_xml.set(u'version', OpenLyrics.IMPLEMENTED_VERSION)
+ song_xml.set(u'createdIn', u'OpenLP 1.9.4') # Use variable
+ song_xml.set(u'modifiedIn', u'OpenLP 1.9.4') # Use variable
+ song_xml.set(u'modifiedDate',
+ datetime.datetime.now().strftime(u'%Y-%m-%dT%H:%M:%S'))
properties = etree.SubElement(song_xml, u'properties')
titles = etree.SubElement(properties, u'titles')
self._add_text_to_element(u'title', titles, song.title.strip())
@@ -237,7 +248,7 @@ class OpenLyrics(object):
self._add_text_to_element(u'copyright', properties, song.copyright)
if song.verse_order:
self._add_text_to_element(
- u'verseOrder', properties, song.verse_order)
+ u'verseOrder', properties, song.verse_order.lower())
if song.ccli_number:
self._add_text_to_element(u'ccliNo', properties, song.ccli_number)
if song.authors:
@@ -252,7 +263,8 @@ class OpenLyrics(object):
songbooks = etree.SubElement(properties, u'songbooks')
element = self._add_text_to_element(
u'songbook', songbooks, None, book)
- element.set(u'entry', song.song_number)
+ if song.song_number:
+ element.set(u'entry', song.song_number)
if song.topics:
themes = etree.SubElement(properties, u'themes')
for topic in song.topics:
@@ -263,6 +275,8 @@ class OpenLyrics(object):
verse[0][u'type'][0].lower(), verse[0][u'label'])
element = \
self._add_text_to_element(u'verse', lyrics, None, verse_tag)
+ if verse[0].has_key(u'lang'):
+ element.set(u'lang', verse[0][u'lang'])
element = self._add_text_to_element(u'lines', element)
for line in unicode(verse[1]).split(u'\n'):
self._add_text_to_element(u'line', element, line)
@@ -450,7 +464,7 @@ class OpenLyrics(object):
text += u'\n'
text += u'\n'.join([unicode(line) for line in lines.line])
verse_name = self._get(verse, u'name')
- verse_type = unicode(VerseType.to_string(verse_name[0]))[0]
+ verse_type = unicode(VerseType.to_string(verse_name[0]))
verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_name)
verse_part = re.compile(u'[0-9]*').sub(u'', verse_name[1:])
# OpenLyrics allows e. g. "c", but we need "c1".
@@ -478,9 +492,9 @@ class OpenLyrics(object):
for name in temp_verse_order:
if name[0] == previous_type:
if name[1] != previous_number:
- verse_order.append(u''.join((name[0], name[1])))
+ verse_order.append(u''.join((name[0][0], name[1])))
else:
- verse_order.append(u''.join((name[0], name[1])))
+ verse_order.append(u''.join((name[0][0], name[1])))
previous_type = name[0]
previous_number = name[1]
previous_part = name[2]
diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py
index 2bd636097..ac41458c2 100644
--- a/openlp/plugins/songs/songsplugin.py
+++ b/openlp/plugins/songs/songsplugin.py
@@ -31,7 +31,6 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.db import Manager
-from openlp.core.lib.ui import UiStrings
from openlp.plugins.songs.lib import SongMediaItem, SongsTab, SongXML
from openlp.plugins.songs.lib.db import Author, init_schema, Song
from openlp.plugins.songs.lib.importer import SongFormat
@@ -52,17 +51,14 @@ class SongsPlugin(Plugin):
"""
Create and set up the Songs plugin.
"""
- Plugin.__init__(self, u'Songs', u'1.9.4', plugin_helpers)
+ Plugin.__init__(self, u'Songs', u'1.9.4', plugin_helpers,
+ SongMediaItem, SongsTab)
self.weight = -10
self.manager = Manager(u'songs', init_schema)
self.icon_path = u':/plugins/plugin_songs.png'
self.icon = build_icon(self.icon_path)
self.whitespace = re.compile(r'\W+', re.UNICODE)
- def getSettingsTab(self):
- visible_name = self.getString(StringContent.VisibleName)
- return SongsTab(self.name, visible_name[u'title'])
-
def initialise(self):
log.info(u'Songs Initialising')
Plugin.initialise(self)
@@ -70,13 +66,6 @@ class SongsPlugin(Plugin):
self.mediaItem.displayResultsSong(
self.manager.get_all_objects(Song, order_by_ref=Song.search_title))
- def getMediaManagerItem(self):
- """
- Create the MediaManagerItem object, which is displaed in the
- Media Manager.
- """
- return SongMediaItem(self, self, self.icon)
-
def addImportMenuItem(self, import_menu):
"""
Give the Songs plugin the opportunity to add items to the
@@ -107,8 +96,17 @@ class SongsPlugin(Plugin):
The actual **Export** menu item, so that your actions can
use it as their parent.
"""
- # No menu items for now.
- pass
+ # Main song import menu item - will eventually be the only one
+ self.SongExportItem = QtGui.QAction(export_menu)
+ self.SongExportItem.setObjectName(u'SongExportItem')
+ self.SongExportItem.setText(translate(
+ 'SongsPlugin', '&Song'))
+ self.SongExportItem.setToolTip(translate('SongsPlugin',
+ 'Exports songs using the export wizard.'))
+ export_menu.addAction(self.SongExportItem)
+ # Signals and slots
+ QtCore.QObject.connect(self.SongExportItem,
+ QtCore.SIGNAL(u'triggered()'), self.onSongExportItemClicked)
def addToolsMenuItem(self, tools_menu):
"""
@@ -184,6 +182,10 @@ class SongsPlugin(Plugin):
if self.mediaItem:
self.mediaItem.onImportClick()
+ def onSongExportItemClicked(self):
+ if self.mediaItem:
+ self.mediaItem.onExportClick()
+
def about(self):
about_text = translate('SongsPlugin', 'Songs Plugin'
'
The songs plugin provides the ability to display and '
@@ -237,7 +239,18 @@ class SongsPlugin(Plugin):
u'title': translate('SongsPlugin', 'Songs', 'container title')
}
# Middle Header Bar
- Plugin.setPluginTextStrings(self)
+ tooltips = {
+ u'load': u'',
+ u'import': u'',
+ u'new': translate('SongsPlugin', 'Add a new Song'),
+ u'edit': translate('SongsPlugin', 'Edit the selected Song'),
+ u'delete': translate('SongsPlugin', 'Delete the selected Song'),
+ u'preview': translate('SongsPlugin', 'Preview the selected Song'),
+ u'live': translate('SongsPlugin', 'Send the selected Song live'),
+ u'service': translate('SongsPlugin',
+ 'Add the selected Song to the service')
+ }
+ self.setPluginUiTextStrings(tooltips)
def finalise(self):
"""
diff --git a/openlp/plugins/songusage/forms/songusagedeletedialog.py b/openlp/plugins/songusage/forms/songusagedeletedialog.py
index af85ad5a9..9dc4219fc 100644
--- a/openlp/plugins/songusage/forms/songusagedeletedialog.py
+++ b/openlp/plugins/songusage/forms/songusagedeletedialog.py
@@ -25,7 +25,9 @@
###############################################################################
from PyQt4 import QtCore, QtGui
+
from openlp.core.lib import translate
+from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_SongUsageDeleteDialog(object):
def setupUi(self, songUsageDeleteDialog):
@@ -43,22 +45,14 @@ class Ui_SongUsageDeleteDialog(object):
QtGui.QCalendarWidget.NoVerticalHeader)
self.deleteCalendar.setObjectName(u'deleteCalendar')
self.verticalLayout.addWidget(self.deleteCalendar)
- self.buttonBox = QtGui.QDialogButtonBox(songUsageDeleteDialog)
+ self.buttonBox = create_accept_reject_button_box(
+ songUsageDeleteDialog, True)
self.buttonBox.setGeometry(QtCore.QRect(30, 210, 245, 25))
- self.buttonBox.setStandardButtons(
- QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(u'buttonBox')
-
self.retranslateUi(songUsageDeleteDialog)
- QtCore.QObject.connect(
- self.buttonBox, QtCore.SIGNAL(u'accepted()'),
- songUsageDeleteDialog.accept)
- QtCore.QObject.connect(
- self.buttonBox, QtCore.SIGNAL(u'rejected()'),
- songUsageDeleteDialog.close)
QtCore.QMetaObject.connectSlotsByName(songUsageDeleteDialog)
def retranslateUi(self, songUsageDeleteDialog):
songUsageDeleteDialog.setWindowTitle(
translate('SongUsagePlugin.SongUsageDeleteForm',
- 'Delete Song Usage Data'))
\ No newline at end of file
+ 'Delete Song Usage Data'))
diff --git a/openlp/plugins/songusage/forms/songusagedetaildialog.py b/openlp/plugins/songusage/forms/songusagedetaildialog.py
index ec1f69d7e..322e3eb4b 100644
--- a/openlp/plugins/songusage/forms/songusagedetaildialog.py
+++ b/openlp/plugins/songusage/forms/songusagedetaildialog.py
@@ -27,6 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon, translate
+from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_SongUsageDetailDialog(object):
def setupUi(self, songUsageDetailDialog):
@@ -71,17 +72,10 @@ class Ui_SongUsageDetailDialog(object):
self.verticalLayout4.addLayout(self.horizontalLayout)
self.verticalLayout2.addWidget(self.fileGroupBox)
self.verticalLayout.addWidget(self.dateRangeGroupBox)
- self.buttonBox = QtGui.QDialogButtonBox(songUsageDetailDialog)
- self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
- QtGui.QDialogButtonBox.Ok)
- self.buttonBox.setObjectName(u'buttonBox')
+ self.buttonBox = create_accept_reject_button_box(
+ songUsageDetailDialog, True)
self.verticalLayout.addWidget(self.buttonBox)
-
self.retranslateUi(songUsageDetailDialog)
- QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'),
- songUsageDetailDialog.accept)
- QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'),
- songUsageDetailDialog.close)
QtCore.QObject.connect(self.saveFilePushButton,
QtCore.SIGNAL(u'pressed()'),
songUsageDetailDialog.defineOutputLocation)
diff --git a/resources/forms/songexport.ui b/resources/forms/songexport.ui
deleted file mode 100644
index 9830db3ef..000000000
--- a/resources/forms/songexport.ui
+++ /dev/null
@@ -1,241 +0,0 @@
-
- SongExportDialog
-
-
-
- 0
- 0
- 641
- 607
-
-
-
- Dialog
-
-
-
- 8
-
-
- 8
-
- -
-
-
-
- 8
-
-
- 0
-
-
-
-
-
- Available Songs
-
-
-
-
-
-
- -
-
-
- Select All
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 30
- 16777215
-
-
-
-
- 8
-
-
- QLayout::SetMinimumSize
-
-
- 0
-
-
-
-
-
- Qt::Vertical
-
-
- QSizePolicy::MinimumExpanding
-
-
-
- 20
- 132
-
-
-
-
- -
-
-
- Select Songs
-
-
-
- :/exports/export_move_to_list.png:/exports/export_move_to_list.png
-
-
-
- 20
- 20
-
-
-
-
- -
-
-
- Deselect Songs
-
-
-
- :/exports/export_remove.png:/exports/export_remove.png
-
-
-
- 20
- 20
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::MinimumExpanding
-
-
-
- 20
- 131
-
-
-
-
-
-
-
- -
-
-
- Selected Songs
-
-
-
-
-
-
- -
-
-
- Select All
-
-
-
-
-
-
-
-
-
- -
-
-
- 0
-
-
-
- OpenLyric Format
-
-
-
-
- Text File
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
-
-
-
-
- SongExportButtonBox
- AvailableListWidget
- AvailableAllToolButton
- SelectToolButton
- DeselectToolButton
- SelectedListWidget
- SelectedAllToolButton
- ExportTabWidget
-
-
-
-
-
-
- SongExportButtonBox
- accepted()
- SongExportDialog
- accept()
-
-
- 248
- 254
-
-
- 157
- 274
-
-
-
-
- SongExportButtonBox
- rejected()
- SongExportDialog
- reject()
-
-
- 316
- 260
-
-
- 286
- 274
-
-
-
-
-
diff --git a/resources/images/bibles_search_reference.png b/resources/images/bibles_search_reference.png
new file mode 100644
index 000000000..f64c0ad78
Binary files /dev/null and b/resources/images/bibles_search_reference.png differ
diff --git a/resources/images/bibles_search_text.png b/resources/images/bibles_search_text.png
new file mode 100644
index 000000000..1ab7145c6
Binary files /dev/null and b/resources/images/bibles_search_text.png differ
diff --git a/resources/images/export_move_to_list.png b/resources/images/export_move_to_list.png
deleted file mode 100644
index 5c0005856..000000000
Binary files a/resources/images/export_move_to_list.png and /dev/null differ
diff --git a/resources/images/export_remove.png b/resources/images/export_remove.png
deleted file mode 100644
index ef8e685e2..000000000
Binary files a/resources/images/export_remove.png and /dev/null differ
diff --git a/resources/images/export_selectall.png b/resources/images/export_selectall.png
deleted file mode 100644
index 0f0d9f152..000000000
Binary files a/resources/images/export_selectall.png and /dev/null differ
diff --git a/resources/images/openlp-2.qrc b/resources/images/openlp-2.qrc
index 2db924363..9e6ff6543 100644
--- a/resources/images/openlp-2.qrc
+++ b/resources/images/openlp-2.qrc
@@ -21,6 +21,10 @@
song_topic_edit.png
song_book_edit.png
+
+ bibles_search_text.png
+ bibles_search_reference.png
+
plugin_alerts.png
plugin_bibles.png
@@ -80,12 +84,10 @@
import_load.png
- export_selectall.png
- export_remove.png
export_load.png
- export_move_to_list.png
+ wizard_exportsong.bmp
wizard_importsong.bmp
wizard_importbible.bmp
wizard_createtheme.bmp
diff --git a/resources/images/wizard_exportsong.bmp b/resources/images/wizard_exportsong.bmp
new file mode 100644
index 000000000..948422dcc
Binary files /dev/null and b/resources/images/wizard_exportsong.bmp differ