diff --git a/documentation/SongFormat.txt b/documentation/SongFormat.txt
deleted file mode 100644
index 31b202dd6..000000000
--- a/documentation/SongFormat.txt
+++ /dev/null
@@ -1,124 +0,0 @@
-openlp.org 2.x Song Database Structure
-========================================================================
-
-Introduction
-------------
-The song database in openlp.org 2.x is similar to the 1.x format. The
-biggest differences are the addition of extra tables, and the use of
-SQLite version 3.
-
-The song database contains the following tables:
-- authors
-- authors_songs
-- song_books
-- songs
-- songs_topics
-- topics
-
-
-"authors" Table
----------------
-This table holds the names of all the authors. It has the following
-columns:
-
-* id
-* first_name
-* last_name
-* display_name
-
-
-"authors_songs" Table
----------------------
-This is a bridging table between the "authors" and "songs" tables, which
-serves to create a many-to-many relationship between the two tables. It
-has the following columns:
-
-* author_id
-* song_id
-
-
-"song_books" Table
-------------------
-The "song_books" table holds a list of books that a congregation gets
-their songs from, or old hymnals now no longer used. This table has the
-following columns:
-
-* id
-* name
-* publisher
-
-
-"songs" Table
--------------
-This table contains the songs, and each song has a list of attributes.
-The "songs" table has the following columns:
-
-* id
-* song_book_id
-* title
-* lyrics
-* verse_order
-* copyright
-* comments
-* ccli_number
-* song_number
-* theme_name
-* search_title
-* search_lyrics
-
-
-"songs_topics" Table
---------------------
-This is a bridging table between the "songs" and "topics" tables, which
-serves to create a many-to-many relationship between the two tables. It
-has the following columns:
-
-* song_id
-* topic_id
-
-
-"topics" Table
---------------
-The topics table holds a selection of topics that songs can cover. This
-is useful when a worship leader wants to select songs with a certain
-theme. This table has the following columns:
-
-* id
-* name
-
-
-The lyrics definition (more or less similar to interformat to/from ChangingSong
-The tags can also be used within the lyrics test.
-
-! Please note that this format has been checked at http://validator.w3.org/#validate_by_upload
-
-
- Amazing Grace
-
- name of verse specific theme (optional)
- any text (optional)
-
- Amazing grace, how ...
-
-
- A b c
- D e f
-
- ...
-
-
- name of verse specific theme (optional)
- any text (optional)
- ...
-
-
-
- Erstaunliche Anmut
-
- Erstaunliche Anmut, wie
- ...
-
-
- ...
-
-
diff --git a/openlp.pyw b/openlp.pyw
index 8d20080c9..100c3336f 100755
--- a/openlp.pyw
+++ b/openlp.pyw
@@ -76,7 +76,7 @@ class OpenLP(QtGui.QApplication):
"""
Load and store current Application Version
"""
- if u'--dev-version' in sys.argv:
+ if u'--dev-version' in sys.argv or u'-d' in sys.argv:
# If we're running the dev version, let's use bzr to get the version
try:
# If bzrlib is availble, use it
@@ -216,6 +216,7 @@ class OpenLP(QtGui.QApplication):
Sets the Busy Cursor for the Application
"""
self.setOverrideCursor(QtCore.Qt.BusyCursor)
+ self.processEvents()
def setNormalCursor(self):
"""
diff --git a/openlp/core/lib/dockwidget.py b/openlp/core/lib/dockwidget.py
index 24841ec33..32d6ce765 100644
--- a/openlp/core/lib/dockwidget.py
+++ b/openlp/core/lib/dockwidget.py
@@ -31,6 +31,8 @@ import logging
from PyQt4 import QtGui
+from openlp.core.lib import build_icon
+
log = logging.getLogger(__name__)
class OpenLPDockWidget(QtGui.QDockWidget):
@@ -47,4 +49,4 @@ class OpenLPDockWidget(QtGui.QDockWidget):
if name:
self.setObjectName(name)
if icon:
- self.setWindowIcon(icon)
+ self.setWindowIcon(build_icon(icon))
diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py
index 39c37e2a9..683459825 100644
--- a/openlp/core/lib/mediamanageritem.py
+++ b/openlp/core/lib/mediamanageritem.py
@@ -366,33 +366,34 @@ class MediaManagerItem(QtGui.QWidget):
count += 1
return filelist
- def validate(self, file, thumb):
+ def validate(self, image, thumb):
"""
- Validates to see if the file still exists or thumbnail is up to date
+ Validates whether an image still exists and, if it does, is the
+ thumbnail representation of the image up to date.
"""
- if not os.path.exists(file):
+ if not os.path.exists(image):
return False
if os.path.exists(thumb):
- filedate = os.stat(file).st_mtime
- thumbdate = os.stat(thumb).st_mtime
- # if file updated rebuild icon
- if filedate > thumbdate:
- self.iconFromFile(file, thumb)
+ imageDate = os.stat(image).st_mtime
+ thumbDate = os.stat(thumb).st_mtime
+ # If image has been updated rebuild icon
+ if imageDate > thumbDate:
+ self.iconFromFile(image, thumb)
else:
- self.iconFromFile(file, thumb)
+ self.iconFromFile(image, thumb)
return True
- def iconFromFile(self, file, thumb):
+ def iconFromFile(self, image, thumb):
"""
- Create a thumbnail icon from a given file
+ Create a thumbnail icon from a given image.
- ``file``
- The file to create the icon from
+ ``image``
+ The image file to create the icon from.
``thumb``
The filename to save the thumbnail to
"""
- icon = build_icon(unicode(file))
+ icon = build_icon(unicode(image))
pixmap = icon.pixmap(QtCore.QSize(88, 50))
ext = os.path.splitext(thumb)[1].lower()
pixmap.save(thumb, ext[1:])
@@ -403,12 +404,16 @@ class MediaManagerItem(QtGui.QWidget):
u'defined by the plugin')
def onNewClick(self):
- raise NotImplementedError(u'MediaManagerItem.onNewClick needs to be '
- u'defined by the plugin')
+ """
+ Hook for plugins to define behaviour for adding new items.
+ """
+ pass
def onEditClick(self):
- raise NotImplementedError(u'MediaManagerItem.onEditClick needs to be '
- u'defined by the plugin')
+ """
+ Hook for plugins to define behaviour for editing items.
+ """
+ pass
def onDeleteClick(self):
raise NotImplementedError(u'MediaManagerItem.onDeleteClick needs to '
diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py
index bb8238bf0..4a346b3e1 100644
--- a/openlp/core/lib/ui.py
+++ b/openlp/core/lib/ui.py
@@ -30,7 +30,7 @@ import logging
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import Receiver, translate
+from openlp.core.lib import build_icon, Receiver, translate
log = logging.getLogger(__name__)
@@ -38,6 +38,9 @@ def add_welcome_page(parent, image):
"""
Generate an opening welcome page for a wizard using a provided image.
+ ``parent``
+ A ``QWizard`` object to add the welcome page to.
+
``image``
A splash image for the wizard.
"""
@@ -58,9 +61,14 @@ def add_welcome_page(parent, image):
parent.welcomeLayout.addStretch()
parent.addPage(parent.welcomePage)
-def save_cancel_button_box(parent):
+def create_save_cancel_button_box(parent):
"""
- Return a standard dialog button box with save and cancel buttons.
+ Creates a standard dialog button box with save and cancel buttons. 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.
"""
button_box = QtGui.QDialogButtonBox(parent)
button_box.setStandardButtons(
@@ -108,3 +116,106 @@ def media_item_combo_box(parent, name):
combo.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToMinimumContentsLength)
combo.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
return combo
+
+def create_delete_push_button(parent, icon=None):
+ """
+ Creates a standard push button with a delete label and optional icon. The
+ button is connected to the parent's ``onDeleteButtonClicked()`` method to
+ handle the ``clicked()`` signal.
+
+ ``parent``
+ The parent object. This should be a ``QWidget`` descendant.
+
+ ``icon``
+ An icon to display on the button. This can be either a ``QIcon``, a
+ resource path or a file name.
+ """
+ delete_button = QtGui.QPushButton(parent)
+ delete_button.setObjectName(u'deleteButton')
+ delete_icon = icon if icon else u':/general/general_delete.png'
+ delete_button.setIcon(build_icon(delete_icon))
+ delete_button.setText(translate('OpenLP.Ui', '&Delete'))
+ delete_button.setToolTip(
+ translate('OpenLP.Ui', 'Delete the selected item.'))
+ QtCore.QObject.connect(delete_button,
+ QtCore.SIGNAL(u'clicked()'), parent.onDeleteButtonClicked)
+ return delete_button
+
+def create_up_down_push_button_set(parent):
+ """
+ Creates a standard set of two push buttons, one for up and the other for
+ down, for use with lists. The buttons use arrow icons and no text and are
+ connected to the parent's ``onUpButtonClicked()`` and
+ ``onDownButtonClicked()`` to handle their respective ``clicked()`` signals.
+
+ ``parent``
+ The parent object. This should be a ``QWidget`` descendant.
+ """
+ up_button = QtGui.QPushButton(parent)
+ up_button.setIcon(build_icon(u':/services/service_up.png'))
+ up_button.setObjectName(u'upButton')
+ up_button.setToolTip(
+ translate('OpenLP.Ui', 'Move selection up one position.'))
+ down_button = QtGui.QPushButton(parent)
+ down_button.setIcon(build_icon(u':/services/service_down.png'))
+ down_button.setObjectName(u'downButton')
+ down_button.setToolTip(
+ translate('OpenLP.Ui', 'Move selection down one position.'))
+ QtCore.QObject.connect(up_button,
+ QtCore.SIGNAL(u'clicked()'), parent.onUpButtonClicked)
+ QtCore.QObject.connect(down_button,
+ QtCore.SIGNAL(u'clicked()'), parent.onDownButtonClicked)
+ return up_button, down_button
+
+def base_action(parent, name):
+ """
+ Return the most basic action with the object name set.
+ """
+ action = QtGui.QAction(parent)
+ action.setObjectName(name)
+ return action
+
+def checkable_action(parent, name, checked=None):
+ """
+ Return a standard action with the checkable attribute set.
+ """
+ action = base_action(parent, name)
+ action.setCheckable(True)
+ if checked is not None:
+ action.setChecked(checked)
+ return action
+
+def icon_action(parent, name, icon, checked=None):
+ """
+ Return a standard action with an icon.
+ """
+ if checked is not None:
+ action = checkable_action(parent, name, checked)
+ else:
+ action = base_action(parent, name)
+ action.setIcon(build_icon(icon))
+ return action
+
+def shortcut_action(parent, text, shortcuts, function):
+ """
+ Return a shortcut enabled action.
+ """
+ action = QtGui.QAction(text, parent)
+ action.setShortcuts(shortcuts)
+ action.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
+ QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), function)
+ return action
+
+def add_widget_completer(cache, widget):
+ """
+ Adds a text autocompleter to a widget.
+
+ ``cache``
+ The list of items to use as suggestions.
+
+ ``widget``
+ The object to use the completer.
+ """
+ completer = QtGui.QCompleter(cache)
+ completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
+ widget.setCompleter(completer)
diff --git a/openlp/core/ui/exceptiondialog.py b/openlp/core/ui/exceptiondialog.py
index 69035dc4d..ba7bab496 100644
--- a/openlp/core/ui/exceptiondialog.py
+++ b/openlp/core/ui/exceptiondialog.py
@@ -46,6 +46,15 @@ class Ui_ExceptionDialog(object):
self.messageLabel.setObjectName(u'messageLabel')
self.messageLayout.addWidget(self.messageLabel)
self.exceptionLayout.addLayout(self.messageLayout)
+ self.descriptionExplanation = QtGui.QLabel(exceptionDialog)
+ self.descriptionExplanation.setObjectName(u'descriptionExplanation')
+ self.exceptionLayout.addWidget(self.descriptionExplanation)
+ self.descriptionTextEdit = QtGui.QPlainTextEdit(exceptionDialog)
+ self.descriptionTextEdit.setObjectName(u'descriptionTextEdit')
+ self.exceptionLayout.addWidget(self.descriptionTextEdit)
+ self.descriptionWordCount = QtGui.QLabel(exceptionDialog)
+ self.descriptionWordCount.setObjectName(u'descriptionWordCount')
+ self.exceptionLayout.addWidget(self.descriptionWordCount)
self.exceptionTextEdit = QtGui.QPlainTextEdit(exceptionDialog)
self.exceptionTextEdit.setReadOnly(True)
self.exceptionTextEdit.setObjectName(u'exceptionTextEdit')
@@ -65,19 +74,31 @@ class Ui_ExceptionDialog(object):
self.saveReportButton.setObjectName(u'saveReportButton')
self.exceptionButtonBox.addButton(self.saveReportButton,
QtGui.QDialogButtonBox.ActionRole)
+ self.attachFileButton = QtGui.QPushButton(exceptionDialog)
+ self.attachFileButton.setIcon(build_icon(u':/general/general_open.png'))
+ self.attachFileButton.setObjectName(u'attachFileButton')
+ self.exceptionButtonBox.addButton(self.attachFileButton,
+ QtGui.QDialogButtonBox.ActionRole)
self.retranslateUi(exceptionDialog)
+ QtCore.QObject.connect(self.descriptionTextEdit,
+ QtCore.SIGNAL(u'textChanged()'), self.onDescriptionUpdated)
QtCore.QObject.connect(self.exceptionButtonBox,
QtCore.SIGNAL(u'rejected()'), exceptionDialog.reject)
QtCore.QObject.connect(self.sendReportButton,
QtCore.SIGNAL(u'pressed()'), self.onSendReportButtonPressed)
QtCore.QObject.connect(self.saveReportButton,
QtCore.SIGNAL(u'pressed()'), self.onSaveReportButtonPressed)
+ QtCore.QObject.connect(self.attachFileButton,
+ QtCore.SIGNAL(u'pressed()'), self.onAttachFileButtonPressed)
QtCore.QMetaObject.connectSlotsByName(exceptionDialog)
def retranslateUi(self, exceptionDialog):
exceptionDialog.setWindowTitle(
translate('OpenLP.ExceptionDialog', 'Error Occurred'))
+ self.descriptionExplanation.setText(translate('OpenLP.ExceptionDialog',
+ 'Please enter a description of what you were doing to cause this '
+ 'error \n(Minimum 20 characters)'))
self.messageLabel.setText(translate('OpenLP.ExceptionDialog', 'Oops! '
'OpenLP hit a problem, and couldn\'t recover. The text in the box '
'below contains information that might be helpful to the OpenLP '
@@ -88,3 +109,5 @@ class Ui_ExceptionDialog(object):
'Send E-Mail'))
self.saveReportButton.setText(translate('OpenLP.ExceptionDialog',
'Save to File'))
+ self.attachFileButton.setText(translate('OpenLP.ExceptionDialog',
+ 'Attach File'))
diff --git a/openlp/core/ui/exceptionform.py b/openlp/core/ui/exceptionform.py
index 347bcf8f1..7f9e23c61 100644
--- a/openlp/core/ui/exceptionform.py
+++ b/openlp/core/ui/exceptionform.py
@@ -70,8 +70,15 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
self.setupUi(self)
self.settingsSection = u'crashreport'
+ def exec_(self):
+ self.descriptionTextEdit.setPlainText(u'')
+ self.onDescriptionUpdated()
+ self.fileAttachment = None
+ return QtGui.QDialog.exec_(self)
+
def _createReport(self):
openlp_version = self.parent().applicationVersion[u'full']
+ description = unicode(self.descriptionTextEdit.toPlainText())
traceback = unicode(self.exceptionTextEdit.toPlainText())
system = unicode(translate('OpenLP.ExceptionForm',
'Platform: %s\n')) % platform.platform()
@@ -90,7 +97,7 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
system = system + u'Desktop: KDE SC\n'
elif os.environ.get(u'GNOME_DESKTOP_SESSION_ID'):
system = system + u'Desktop: GNOME\n'
- return (openlp_version, traceback, system, libraries)
+ return (openlp_version, description, traceback, system, libraries)
def onSaveReportButtonPressed(self):
"""
@@ -99,6 +106,7 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
report = unicode(translate('OpenLP.ExceptionForm',
'**OpenLP Bug Report**\n'
'Version: %s\n\n'
+ '--- Details of the Exception. ---\n\n%s\n\n '
'--- Exception Traceback ---\n%s\n'
'--- System information ---\n%s\n'
'--- Library Versions ---\n%s\n'))
@@ -132,18 +140,48 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
body = unicode(translate('OpenLP.ExceptionForm',
'*OpenLP Bug Report*\n'
'Version: %s\n\n'
- '--- Please enter the report below this line. ---\n\n\n'
+ '--- Details of the Exception. ---\n\n%s\n\n '
'--- Exception Traceback ---\n%s\n'
'--- System information ---\n%s\n'
'--- Library Versions ---\n%s\n',
'Please add the information that bug reports are favoured written '
'in English.'))
content = self._createReport()
- for line in content[1].split(u'\n'):
+ for line in content[2].split(u'\n'):
if re.search(r'[/\\]openlp[/\\]', line):
source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line)
if u':' in line:
exception = line.split(u'\n')[-1].split(u':')[0]
subject = u'Bug report: %s in %s' % (exception, source)
- mailto(address=u'bugs@openlp.org', subject=subject,
- body=body % content)
+ if self.fileAttachment:
+ mailto(address=u'bugs@openlp.org', subject=subject,
+ body=body % content, attach=self.fileAttachment)
+ else:
+ mailto(address=u'bugs@openlp.org', subject=subject,
+ body=body % content)
+
+ def onDescriptionUpdated(self):
+ count = int(20 - len(self.descriptionTextEdit.toPlainText()))
+ if count < 0:
+ count = 0
+ self.__buttonState(True)
+ else:
+ self.__buttonState(False)
+ self.descriptionWordCount.setText(
+ unicode(translate('OpenLP.ExceptionDialog',
+ 'Description characters to enter : %s')) % count )
+
+ def onAttachFileButtonPressed(self):
+ files = QtGui.QFileDialog.getOpenFileName(
+ self,translate('ImagePlugin.ExceptionDialog',
+ 'Select Attachment'),
+ SettingsManager.get_last_dir(u'exceptions'),
+ u'%s (*.*) (*)' %
+ unicode(translate('ImagePlugin.MediaItem', 'All Files')))
+ log.info(u'New files(s) %s', unicode(files))
+ if files:
+ self.fileAttachment = unicode(files)
+
+ def __buttonState(self, state):
+ self.saveReportButton.setEnabled(state)
+ self.sendReportButton.setEnabled(state)
diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py
index 6f57861c4..9af4931fb 100644
--- a/openlp/core/ui/mainwindow.py
+++ b/openlp/core/ui/mainwindow.py
@@ -28,11 +28,12 @@ import logging
from PyQt4 import QtCore, QtGui
+from openlp.core.lib import RenderManager, build_icon, OpenLPDockWidget, \
+ SettingsManager, PluginManager, Receiver, translate
+from openlp.core.lib.ui import base_action, checkable_action, icon_action
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \
ThemeManager, SlideController, PluginForm, MediaDockManager, \
ShortcutListForm
-from openlp.core.lib import RenderManager, build_icon, OpenLPDockWidget, \
- SettingsManager, PluginManager, Receiver, translate
from openlp.core.utils import AppLocation, add_actions, LanguageManager, \
ActionList
@@ -124,9 +125,8 @@ class Ui_MainWindow(object):
self.DefaultThemeLabel.setObjectName(u'DefaultThemeLabel')
self.StatusBar.addPermanentWidget(self.DefaultThemeLabel)
# Create the MediaManager
- self.MediaManagerDock = OpenLPDockWidget(
- mainWindow, u'MediaManagerDock',
- build_icon(u':/system/system_mediamanager.png'))
+ self.MediaManagerDock = OpenLPDockWidget(mainWindow,
+ u'MediaManagerDock', u':/system/system_mediamanager.png')
self.MediaManagerDock.setStyleSheet(MEDIA_MANAGER_STYLE)
self.MediaManagerDock.setMinimumWidth(
self.settingsmanager.mainwindow_left)
@@ -137,9 +137,8 @@ class Ui_MainWindow(object):
mainWindow.addDockWidget(QtCore.Qt.LeftDockWidgetArea,
self.MediaManagerDock)
# Create the service manager
- self.ServiceManagerDock = OpenLPDockWidget(
- mainWindow, u'ServiceManagerDock',
- build_icon(u':/system/system_servicemanager.png'))
+ self.ServiceManagerDock = OpenLPDockWidget(mainWindow,
+ u'ServiceManagerDock', u':/system/system_servicemanager.png')
self.ServiceManagerDock.setMinimumWidth(
self.settingsmanager.mainwindow_right)
self.ServiceManagerContents = ServiceManager(mainWindow,
@@ -148,9 +147,8 @@ class Ui_MainWindow(object):
mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea,
self.ServiceManagerDock)
# Create the theme manager
- self.ThemeManagerDock = OpenLPDockWidget(
- mainWindow, u'ThemeManagerDock',
- build_icon(u':/system/system_thememanager.png'))
+ self.ThemeManagerDock = OpenLPDockWidget(mainWindow,
+ u'ThemeManagerDock', u':/system/system_thememanager.png')
self.ThemeManagerDock.setMinimumWidth(
self.settingsmanager.mainwindow_right)
self.ThemeManagerContents = ThemeManager(mainWindow,
@@ -160,103 +158,70 @@ class Ui_MainWindow(object):
mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea,
self.ThemeManagerDock)
# Create the menu items
- self.FileNewItem = QtGui.QAction(mainWindow)
- self.FileNewItem.setIcon(build_icon(u':/general/general_new.png'))
- self.FileNewItem.setObjectName(u'FileNewItem')
+ self.FileNewItem = icon_action(mainWindow, u'FileNewItem',
+ u':/general/general_new.png')
mainWindow.actionList.add_action(self.FileNewItem, u'File')
- self.FileOpenItem = QtGui.QAction(mainWindow)
- self.FileOpenItem.setIcon(build_icon(u':/general/general_open.png'))
- self.FileOpenItem.setObjectName(u'FileOpenItem')
+ self.FileOpenItem = icon_action(mainWindow, u'FileOpenItem',
+ u':/general/general_open.png')
mainWindow.actionList.add_action(self.FileOpenItem, u'File')
- self.FileSaveItem = QtGui.QAction(mainWindow)
- self.FileSaveItem.setIcon(build_icon(u':/general/general_save.png'))
- self.FileSaveItem.setObjectName(u'FileSaveItem')
+ self.FileSaveItem = icon_action(mainWindow, u'FileSaveItem',
+ u':/general/general_save.png')
mainWindow.actionList.add_action(self.FileSaveItem, u'File')
- self.FileSaveAsItem = QtGui.QAction(mainWindow)
- self.FileSaveAsItem.setObjectName(u'FileSaveAsItem')
+ self.FileSaveAsItem = base_action(mainWindow, u'FileSaveAsItem')
mainWindow.actionList.add_action(self.FileSaveAsItem, u'File')
- self.printServiceOrderItem = QtGui.QAction(mainWindow)
- self.printServiceOrderItem.setObjectName(u'printServiceItem')
+ self.printServiceOrderItem = base_action(
+ mainWindow, u'printServiceItem')
mainWindow.actionList.add_action(
self.printServiceOrderItem, u'Print Service Order')
- self.FileExitItem = QtGui.QAction(mainWindow)
- self.FileExitItem.setIcon(build_icon(u':/system/system_exit.png'))
- self.FileExitItem.setObjectName(u'FileExitItem')
+ self.FileExitItem = icon_action(mainWindow, u'FileExitItem',
+ u':/system/system_exit.png')
mainWindow.actionList.add_action(self.FileExitItem, u'File')
- self.ImportThemeItem = QtGui.QAction(mainWindow)
- self.ImportThemeItem.setObjectName(u'ImportThemeItem')
+ self.ImportThemeItem = base_action(mainWindow, u'ImportThemeItem')
mainWindow.actionList.add_action(self.ImportThemeItem, u'Import')
- self.ImportLanguageItem = QtGui.QAction(mainWindow)
- self.ImportLanguageItem.setObjectName(u'ImportLanguageItem')
+ self.ImportLanguageItem = base_action(mainWindow, u'ImportLanguageItem')
mainWindow.actionList.add_action(self.ImportLanguageItem, u'Import')
- self.ExportThemeItem = QtGui.QAction(mainWindow)
- self.ExportThemeItem.setObjectName(u'ExportThemeItem')
+ self.ExportThemeItem = base_action(mainWindow, u'ExportThemeItem')
mainWindow.actionList.add_action(self.ExportThemeItem, u'Export')
- self.ExportLanguageItem = QtGui.QAction(mainWindow)
- self.ExportLanguageItem.setObjectName(u'ExportLanguageItem')
+ self.ExportLanguageItem = base_action(mainWindow, u'ExportLanguageItem')
mainWindow.actionList.add_action(self.ExportLanguageItem, u'Export')
- self.ViewMediaManagerItem = QtGui.QAction(mainWindow)
- self.ViewMediaManagerItem.setCheckable(True)
- self.ViewMediaManagerItem.setChecked(self.MediaManagerDock.isVisible())
- self.ViewMediaManagerItem.setIcon(
- build_icon(u':/system/system_mediamanager.png'))
- self.ViewMediaManagerItem.setObjectName(u'ViewMediaManagerItem')
- self.ViewThemeManagerItem = QtGui.QAction(mainWindow)
- self.ViewThemeManagerItem.setCheckable(True)
- self.ViewThemeManagerItem.setChecked(self.ThemeManagerDock.isVisible())
- self.ViewThemeManagerItem.setIcon(
- build_icon(u':/system/system_thememanager.png'))
- self.ViewThemeManagerItem.setObjectName(u'ViewThemeManagerItem')
+ self.ViewMediaManagerItem = icon_action(mainWindow,
+ u'ViewMediaManagerItem', u':/system/system_mediamanager.png',
+ self.MediaManagerDock.isVisible())
+ self.ViewThemeManagerItem = icon_action(mainWindow,
+ u'ViewThemeManagerItem', u':/system/system_thememanager.png',
+ self.ThemeManagerDock.isVisible())
mainWindow.actionList.add_action(self.ViewMediaManagerItem, u'View')
- self.ViewServiceManagerItem = QtGui.QAction(mainWindow)
- self.ViewServiceManagerItem.setCheckable(True)
- self.ViewServiceManagerItem.setChecked(
+ self.ViewServiceManagerItem = icon_action(mainWindow,
+ u'ViewServiceManagerItem', u':/system/system_servicemanager.png',
self.ServiceManagerDock.isVisible())
- self.ViewServiceManagerItem.setIcon(
- build_icon(u':/system/system_servicemanager.png'))
- self.ViewServiceManagerItem.setObjectName(u'ViewServiceManagerItem')
mainWindow.actionList.add_action(self.ViewServiceManagerItem, u'View')
- self.ViewPreviewPanel = QtGui.QAction(mainWindow)
- self.ViewPreviewPanel.setCheckable(True)
- self.ViewPreviewPanel.setChecked(previewVisible)
- self.ViewPreviewPanel.setObjectName(u'ViewPreviewPanel')
+ self.ViewPreviewPanel = checkable_action(mainWindow,
+ u'ViewPreviewPanel', previewVisible)
mainWindow.actionList.add_action(self.ViewPreviewPanel, u'View')
- self.ViewLivePanel = QtGui.QAction(mainWindow)
- self.ViewLivePanel.setCheckable(True)
- self.ViewLivePanel.setChecked(liveVisible)
- self.ViewLivePanel.setObjectName(u'ViewLivePanel')
+ self.ViewLivePanel = checkable_action(mainWindow, u'ViewLivePanel',
+ liveVisible)
mainWindow.actionList.add_action(self.ViewLivePanel, u'View')
- self.ModeDefaultItem = QtGui.QAction(mainWindow)
- self.ModeDefaultItem.setCheckable(True)
- self.ModeDefaultItem.setObjectName(u'ModeDefaultItem')
+ self.ModeDefaultItem = checkable_action(mainWindow, u'ModeDefaultItem')
mainWindow.actionList.add_action(self.ModeDefaultItem, u'View Mode')
- self.ModeSetupItem = QtGui.QAction(mainWindow)
- self.ModeSetupItem.setCheckable(True)
- self.ModeSetupItem.setObjectName(u'ModeLiveItem')
+ self.ModeSetupItem = checkable_action(mainWindow, u'ModeLiveItem')
mainWindow.actionList.add_action(self.ModeSetupItem, u'View Mode')
- self.ModeLiveItem = QtGui.QAction(mainWindow)
- self.ModeLiveItem.setCheckable(True)
- self.ModeLiveItem.setObjectName(u'ModeLiveItem')
+ self.ModeLiveItem = checkable_action(mainWindow, u'ModeLiveItem')
mainWindow.actionList.add_action(self.ModeLiveItem, u'View Mode')
self.ModeGroup = QtGui.QActionGroup(mainWindow)
self.ModeGroup.addAction(self.ModeDefaultItem)
self.ModeGroup.addAction(self.ModeSetupItem)
self.ModeGroup.addAction(self.ModeLiveItem)
self.ModeDefaultItem.setChecked(True)
- self.ToolsAddToolItem = QtGui.QAction(mainWindow)
- self.ToolsAddToolItem.setIcon(build_icon(u':/tools/tools_add.png'))
- self.ToolsAddToolItem.setObjectName(u'ToolsAddToolItem')
+ self.ToolsAddToolItem = icon_action(mainWindow, u'ToolsAddToolItem',
+ u':/tools/tools_add.png')
mainWindow.actionList.add_action(self.ToolsAddToolItem, u'Tools')
- self.SettingsPluginListItem = QtGui.QAction(mainWindow)
- self.SettingsPluginListItem.setIcon(
- build_icon(u':/system/settings_plugin_list.png'))
- self.SettingsPluginListItem.setObjectName(u'SettingsPluginListItem')
+ self.SettingsPluginListItem = icon_action(mainWindow,
+ u'SettingsPluginListItem', u':/system/settings_plugin_list.png')
mainWindow.actionList.add_action(self.SettingsPluginListItem,
u'Settings')
# i18n Language Items
- self.AutoLanguageItem = QtGui.QAction(mainWindow)
- self.AutoLanguageItem.setObjectName(u'AutoLanguageItem')
- self.AutoLanguageItem.setCheckable(True)
+ self.AutoLanguageItem = checkable_action(mainWindow,
+ u'AutoLanguageItem')
mainWindow.actionList.add_action(self.AutoLanguageItem, u'Settings')
self.LanguageGroup = QtGui.QActionGroup(mainWindow)
self.LanguageGroup.setExclusive(True)
@@ -266,39 +231,28 @@ class Ui_MainWindow(object):
qmList = LanguageManager.get_qm_list()
savedLanguage = LanguageManager.get_language()
for key in sorted(qmList.keys()):
- languageItem = QtGui.QAction(mainWindow)
- languageItem.setObjectName(key)
- languageItem.setCheckable(True)
+ languageItem = checkable_action(mainWindow, key)
if qmList[key] == savedLanguage:
languageItem.setChecked(True)
add_actions(self.LanguageGroup, [languageItem])
- self.SettingsShortcutsItem = QtGui.QAction(mainWindow)
- self.SettingsShortcutsItem.setIcon(
- build_icon(u':/system/system_configure_shortcuts.png'))
- self.SettingsShortcutsItem.setObjectName(u'SettingsShortcutsItem')
- self.SettingsConfigureItem = QtGui.QAction(mainWindow)
- self.SettingsConfigureItem.setIcon(
- build_icon(u':/system/system_settings.png'))
- self.SettingsConfigureItem.setObjectName(u'SettingsConfigureItem')
+ self.SettingsShortcutsItem = icon_action(mainWindow,
+ u'SettingsShortcutsItem',
+ u':/system/system_configure_shortcuts.png')
+ self.SettingsConfigureItem = icon_action(mainWindow,
+ u'SettingsConfigureItem', u':/system/system_settings.png')
mainWindow.actionList.add_action(self.SettingsShortcutsItem,
u'Settings')
- self.HelpDocumentationItem = QtGui.QAction(mainWindow)
- self.HelpDocumentationItem.setIcon(
- build_icon(u':/system/system_help_contents.png'))
- self.HelpDocumentationItem.setObjectName(u'HelpDocumentationItem')
+ self.HelpDocumentationItem = icon_action(mainWindow,
+ u'HelpDocumentationItem', u':/system/system_help_contents.png')
self.HelpDocumentationItem.setEnabled(False)
mainWindow.actionList.add_action(self.HelpDocumentationItem, u'Help')
- self.HelpAboutItem = QtGui.QAction(mainWindow)
- self.HelpAboutItem.setIcon(
- build_icon(u':/system/system_about.png'))
- self.HelpAboutItem.setObjectName(u'HelpAboutItem')
+ self.HelpAboutItem = icon_action(mainWindow, u'HelpAboutItem',
+ u':/system/system_about.png')
mainWindow.actionList.add_action(self.HelpAboutItem, u'Help')
- self.HelpOnlineHelpItem = QtGui.QAction(mainWindow)
- self.HelpOnlineHelpItem.setObjectName(u'HelpOnlineHelpItem')
+ self.HelpOnlineHelpItem = base_action(mainWindow, u'HelpOnlineHelpItem')
self.HelpOnlineHelpItem.setEnabled(False)
mainWindow.actionList.add_action(self.HelpOnlineHelpItem, u'Help')
- self.HelpWebSiteItem = QtGui.QAction(mainWindow)
- self.HelpWebSiteItem.setObjectName(u'HelpWebSiteItem')
+ self.HelpWebSiteItem = base_action(mainWindow, u'HelpWebSiteItem')
mainWindow.actionList.add_action(self.HelpWebSiteItem, u'Help')
add_actions(self.FileImportMenu,
(self.ImportThemeItem, self.ImportLanguageItem))
@@ -999,8 +953,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0]
self.FileMenu.clear()
add_actions(self.FileMenu, self.FileMenuActions[:-1])
- existingRecentFiles = [file for file in self.recentFiles
- if QtCore.QFile.exists(file)]
+ existingRecentFiles = [recentFile for recentFile in self.recentFiles
+ if QtCore.QFile.exists(recentFile)]
recentFilesToDisplay = existingRecentFiles[0:recentFileCount]
if recentFilesToDisplay:
self.FileMenu.addSeparator()
diff --git a/openlp/core/ui/serviceitemeditdialog.py b/openlp/core/ui/serviceitemeditdialog.py
index d4c86fa61..f22f3dcf5 100644
--- a/openlp/core/ui/serviceitemeditdialog.py
+++ b/openlp/core/ui/serviceitemeditdialog.py
@@ -26,8 +26,9 @@
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import translate, build_icon
-from openlp.core.lib.ui import save_cancel_button_box
+from openlp.core.lib import translate
+from openlp.core.lib.ui import create_save_cancel_button_box, \
+ create_delete_push_button, create_up_down_push_button_set
class Ui_ServiceItemEditDialog(object):
def setupUi(self, serviceItemEditDialog):
@@ -40,26 +41,19 @@ class Ui_ServiceItemEditDialog(object):
self.dialogLayout.addWidget(self.listWidget, 0, 0)
self.buttonLayout = QtGui.QVBoxLayout()
self.buttonLayout.setObjectName(u'buttonLayout')
- self.deleteButton = QtGui.QPushButton(serviceItemEditDialog)
- self.deleteButton.setObjectName(u'deleteButton')
+ self.deleteButton = create_delete_push_button(serviceItemEditDialog)
self.buttonLayout.addWidget(self.deleteButton)
self.buttonLayout.addStretch()
- self.upButton = QtGui.QPushButton(serviceItemEditDialog)
- self.upButton.setIcon(build_icon(u':/services/service_up.png'))
- self.upButton.setObjectName(u'upButton')
+ self.upButton, self.downButton = create_up_down_push_button_set(
+ serviceItemEditDialog)
self.buttonLayout.addWidget(self.upButton)
- self.downButton = QtGui.QPushButton(serviceItemEditDialog)
- self.downButton.setIcon(build_icon(u':/services/service_down.png'))
- self.downButton.setObjectName(u'downButton')
self.buttonLayout.addWidget(self.downButton)
self.dialogLayout.addLayout(self.buttonLayout, 0, 1)
self.dialogLayout.addWidget(
- save_cancel_button_box(serviceItemEditDialog), 1, 0, 1, 2)
+ create_save_cancel_button_box(serviceItemEditDialog), 1, 0, 1, 2)
self.retranslateUi(serviceItemEditDialog)
QtCore.QMetaObject.connectSlotsByName(serviceItemEditDialog)
def retranslateUi(self, serviceItemEditDialog):
serviceItemEditDialog.setWindowTitle(
translate('OpenLP.ServiceItemEditForm', 'Reorder Service Item'))
- self.deleteButton.setText(translate('OpenLP.ServiceItemEditForm',
- 'Delete'))
diff --git a/openlp/core/ui/serviceitemeditform.py b/openlp/core/ui/serviceitemeditform.py
index 0621a44bd..70518f30c 100644
--- a/openlp/core/ui/serviceitemeditform.py
+++ b/openlp/core/ui/serviceitemeditform.py
@@ -39,13 +39,6 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
self.itemList = []
- # enable drop
- QtCore.QObject.connect(self.upButton,
- QtCore.SIGNAL(u'clicked()'), self.onItemUp)
- QtCore.QObject.connect(self.downButton,
- QtCore.SIGNAL(u'clicked()'), self.onItemDown)
- QtCore.QObject.connect(self.deleteButton,
- QtCore.SIGNAL(u'clicked()'), self.onItemDelete)
QtCore.QObject.connect(self.listWidget,
QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
@@ -77,7 +70,7 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
item_name = QtGui.QListWidgetItem(frame[u'title'])
self.listWidget.addItem(item_name)
- def onItemDelete(self):
+ def onDeleteButtonClicked(self):
"""
Delete the current row.
"""
@@ -92,13 +85,13 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
else:
self.listWidget.setCurrentRow(row)
- def onItemUp(self):
+ def onUpButtonClicked(self):
"""
Move the current row up in the list.
"""
self.__moveItem(u'up')
- def onItemDown(self):
+ def onDownButtonClicked(self):
"""
Move the current row down in the list
"""
diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py
index 4d36f4aec..bddd150b8 100644
--- a/openlp/core/ui/servicemanager.py
+++ b/openlp/core/ui/servicemanager.py
@@ -507,7 +507,6 @@ class ServiceManager(QtGui.QWidget):
p_file = filePath
if 'p_file' in locals():
Receiver.send_message(u'cursor_busy')
- Receiver.send_message(u'openlp_process_events')
fileTo = open(p_file, u'r')
items = cPickle.load(fileTo)
fileTo.close()
diff --git a/openlp/core/ui/servicenoteform.py b/openlp/core/ui/servicenoteform.py
index e659e50db..473cc1685 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 save_cancel_button_box
+from openlp.core.lib.ui import create_save_cancel_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(save_cancel_button_box(self))
+ self.dialogLayout.addWidget(create_save_cancel_button_box(self))
QtCore.QMetaObject.connectSlotsByName(self)
def retranslateUi(self):
diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py
index ab8a656ff..bf0453e05 100644
--- a/openlp/core/ui/slidecontroller.py
+++ b/openlp/core/ui/slidecontroller.py
@@ -30,9 +30,10 @@ import os
from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon
-from openlp.core.ui import HideMode, MainDisplay
from openlp.core.lib import OpenLPToolbar, Receiver, resize_image, \
ItemCapabilities, translate
+from openlp.core.lib.ui import shortcut_action
+from openlp.core.ui import HideMode, MainDisplay
log = logging.getLogger(__name__)
@@ -317,18 +318,8 @@ class SlideController(QtGui.QWidget):
self.mediabar.setVisible(False)
if self.isLive:
self.setLiveHotkeys(self)
- self.previewListWidget.addActions(
- [self.previousItem,
- self.nextItem,
- self.previousService,
- self.nextService,
- self.escapeItem])
- self.display.addActions(
- [self.previousItem,
- self.nextItem,
- self.previousService,
- self.nextService,
- self.escapeItem])
+ self.__addActionsToWidget(self.previewListWidget)
+ self.__addActionsToWidget(self.display)
else:
self.setPreviewHotkeys()
self.previewListWidget.addActions(
@@ -390,28 +381,17 @@ class SlideController(QtGui.QWidget):
self.nextItem.setShortcuts([QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown])
self.nextItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
actionList.add_action(self.nextItem, u'Live')
- self.previousService = QtGui.QAction(translate(
- 'OpenLP.SlideController', 'Previous Service'), parent)
- self.previousService.setShortcuts([QtCore.Qt.Key_Left, 0])
- self.previousService.setShortcutContext(
- QtCore.Qt.WidgetWithChildrenShortcut)
- QtCore.QObject.connect(self.previousService,
- QtCore.SIGNAL(u'triggered()'), self.servicePrevious)
+ self.previousService = shortcut_action(parent,
+ translate('OpenLP.SlideController', 'Previous Service'),
+ [QtCore.Qt.Key_Left, 0], self.servicePrevious)
actionList.add_action(self.previousService, u'Live')
- self.nextService = QtGui.QAction(translate(
- 'OpenLP.SlideController', 'Next Service'), parent)
- self.nextService.setShortcuts([QtCore.Qt.Key_Right, 0])
- self.nextService.setShortcutContext(
- QtCore.Qt.WidgetWithChildrenShortcut)
- QtCore.QObject.connect(self.nextService,
- QtCore.SIGNAL(u'triggered()'), self.serviceNext)
+ self.nextService = shortcut_action(parent,
+ translate('OpenLP.SlideController', 'Next Service'),
+ [QtCore.Qt.Key_Right, 0], self.serviceNext)
actionList.add_action(self.nextService, u'Live')
- self.escapeItem = QtGui.QAction(translate(
- 'OpenLP.SlideController', 'Escape Item'), parent)
- self.escapeItem.setShortcuts([QtCore.Qt.Key_Escape, 0])
- self.escapeItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
- QtCore.QObject.connect(self.escapeItem,
- QtCore.SIGNAL(u'triggered()'), self.liveEscape)
+ self.escapeItem = shortcut_action(parent,
+ translate('OpenLP.SlideController', 'Escape Item'),
+ [QtCore.Qt.Key_Escape, 0], self.liveEscape)
actionList.add_action(self.escapeItem, u'Live')
def liveEscape(self):
@@ -435,12 +415,7 @@ class SlideController(QtGui.QWidget):
self.display.alertTab = self.alertTab
self.display.setup()
if self.isLive:
- self.display.addActions(
- [self.previousItem,
- self.nextItem,
- self.previousService,
- self.nextService,
- self.escapeItem])
+ self.__addActionsToWidget(self.display)
# The SlidePreview's ratio.
self.ratio = float(self.screens.current[u'size'].width()) / \
float(self.screens.current[u'size'].height())
@@ -448,6 +423,12 @@ class SlideController(QtGui.QWidget):
if self.serviceItem:
self.refreshServiceItem()
+ def __addActionsToWidget(self, widget):
+ widget.addActions([
+ self.previousItem, self.nextItem,
+ self.previousService, self.nextService,
+ self.escapeItem])
+
def previewSizeChanged(self):
"""
Takes care of the SlidePreview's size. Is called when one of the the
@@ -575,10 +556,7 @@ class SlideController(QtGui.QWidget):
slideno = 0
# If service item is the same as the current on only change slide
if item.__eq__(self.serviceItem):
- if slideno + 1 < self.previewListWidget.rowCount():
- self.previewListWidget.scrollToItem(
- self.previewListWidget.item(slideno + 1, 0))
- self.previewListWidget.selectRow(slideno)
+ self.__checkUpdateSelectedSlide(slideno)
self.onSlideSelected()
return
self._processItem(item, slideno)
@@ -677,10 +655,7 @@ class SlideController(QtGui.QWidget):
self.previewListWidget.selectRow(
self.previewListWidget.rowCount() - 1)
else:
- if slideno + 1 < self.previewListWidget.rowCount():
- self.previewListWidget.scrollToItem(
- self.previewListWidget.item(slideno + 1, 0))
- self.previewListWidget.selectRow(slideno)
+ self.__checkUpdateSelectedSlide(slideno)
def onTextRequest(self):
"""
@@ -729,10 +704,7 @@ class SlideController(QtGui.QWidget):
[self.serviceItem, self.isLive, index])
self.updatePreview()
else:
- if index + 1 < self.previewListWidget.rowCount():
- self.previewListWidget.scrollToItem(
- self.previewListWidget.item(index + 1, 0))
- self.previewListWidget.selectRow(index)
+ self.__checkUpdateSelectedSlide(index)
self.onSlideSelected()
def mainDisplaySetBackground(self):
@@ -891,10 +863,7 @@ class SlideController(QtGui.QWidget):
"""
The slide has been changed. Update the slidecontroller accordingly
"""
- if row + 1 < self.previewListWidget.rowCount():
- self.previewListWidget.scrollToItem(
- self.previewListWidget.item(row + 1, 0))
- self.previewListWidget.selectRow(row)
+ self.__checkUpdateSelectedSlide(row)
self.updatePreview()
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
row)
@@ -945,10 +914,7 @@ class SlideController(QtGui.QWidget):
else:
Receiver.send_message('servicemanager_next_item')
return
- if row + 1 < self.previewListWidget.rowCount():
- self.previewListWidget.scrollToItem(
- self.previewListWidget.item(row + 1, 0))
- self.previewListWidget.selectRow(row)
+ self.__checkUpdateSelectedSlide(row)
self.onSlideSelected()
def onSlideSelectedPreviousNoloop(self):
@@ -971,12 +937,15 @@ class SlideController(QtGui.QWidget):
row = self.previewListWidget.rowCount() - 1
else:
row = 0
- if row + 1 < self.previewListWidget.rowCount():
- self.previewListWidget.scrollToItem(
- self.previewListWidget.item(row + 1, 0))
- self.previewListWidget.selectRow(row)
+ self.__checkUpdateSelectedSlide(row)
self.onSlideSelected()
+ def __checkUpdateSelectedSlide(self, row):
+ if row + 1 < self.previewListWidget.rowCount():
+ self.previewListWidget.scrollToItem(
+ self.previewListWidget.item(row + 1, 0))
+ self.previewListWidget.selectRow(row)
+
def onSlideSelectedLast(self):
"""
Go to the last slide.
diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py
index f403d7441..7a4dda882 100644
--- a/openlp/core/ui/thememanager.py
+++ b/openlp/core/ui/thememanager.py
@@ -241,7 +241,7 @@ class ThemeManager(QtGui.QWidget):
QtCore.QVariant(self.global_theme))
Receiver.send_message(u'theme_update_global',
self.global_theme)
- self.pushThemes()
+ self._pushThemes()
def onAddTheme(self):
"""
@@ -268,11 +268,12 @@ class ThemeManager(QtGui.QWidget):
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text())
if self.checkIfThemeExists(newThemeName):
oldThemeData = self.getThemeData(oldThemeName)
- self.deleteTheme(oldThemeName)
self.cloneThemeData(oldThemeData, newThemeName)
+ self.deleteTheme(oldThemeName)
for plugin in self.mainwindow.pluginManager.plugins:
if plugin.usesTheme(oldThemeName):
plugin.renameTheme(oldThemeName, newThemeName)
+ self.loadThemes()
def onCopyTheme(self):
"""
@@ -300,6 +301,7 @@ class ThemeManager(QtGui.QWidget):
os.path.split(unicode(themeData.background_filename))[1])
saveFrom = themeData.background_filename
themeData.theme_name = newThemeName
+ themeData.extend_image_filename(self.path)
self.saveTheme(themeData, saveFrom, saveTo)
def onEditTheme(self):
@@ -332,6 +334,10 @@ class ThemeManager(QtGui.QWidget):
row = self.themeListWidget.row(item)
self.themeListWidget.takeItem(row)
self.deleteTheme(theme)
+ # As we do not reload the themes, push out the change
+ # Reaload the list as the internal lists and events need
+ # to be triggered
+ self._pushThemes()
def deleteTheme(self, theme):
"""
@@ -349,10 +355,6 @@ class ThemeManager(QtGui.QWidget):
shutil.rmtree(os.path.join(self.path, theme).encode(encoding))
except OSError:
log.exception(u'Error deleting theme %s', theme)
- # As we do not reload the themes push out the change
- # Reaload the list as the internal lists and events need
- # to be triggered
- self.pushThemes()
def onExportTheme(self):
"""
@@ -449,9 +451,9 @@ class ThemeManager(QtGui.QWidget):
QtCore.QVariant(textName))
self.themeListWidget.addItem(item_name)
self.themelist.append(textName)
- self.pushThemes()
+ self._pushThemes()
- def pushThemes(self):
+ def _pushThemes(self):
"""
Notify listeners that the theme list has been updated
"""
@@ -571,6 +573,14 @@ class ThemeManager(QtGui.QWidget):
Called by thememaintenance Dialog to save the theme
and to trigger the reload of the theme list
"""
+ self._writeTheme(theme, imageFrom, imageTo)
+ self.loadThemes()
+
+ def _writeTheme(self, theme, imageFrom, imageTo):
+ """
+ Writes the theme to the disk and handles the background image if
+ necessary
+ """
name = theme.theme_name
theme_pretty_xml = theme.extract_formatted_xml()
log.debug(u'saveTheme %s %s', name, theme_pretty_xml)
@@ -598,12 +608,9 @@ class ThemeManager(QtGui.QWidget):
except IOError:
log.exception(u'Failed to save theme image')
self.generateAndSaveImage(self.path, name, theme)
- self.loadThemes()
- self.pushThemes()
def generateAndSaveImage(self, dir, name, theme):
log.debug(u'generateAndSaveImage %s %s', dir, name)
- theme_xml = theme.extract_xml()
frame = self.generateImage(theme)
samplepathname = os.path.join(self.path, name + u'.png')
if os.path.exists(samplepathname):
diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py
index e8765b9e2..49522df70 100644
--- a/openlp/core/ui/themewizard.py
+++ b/openlp/core/ui/themewizard.py
@@ -36,6 +36,8 @@ class Ui_ThemeWizard(object):
themeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
themeWizard.setOptions(QtGui.QWizard.IndependentPages |
QtGui.QWizard.NoBackButtonOnStartPage)
+ self.spacer = QtGui.QSpacerItem(10, 0,
+ QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
# Welcome Page
add_welcome_page(themeWizard, u':/wizards/wizard_createtheme.bmp')
# Background Page
@@ -52,10 +54,8 @@ class Ui_ThemeWizard(object):
self.backgroundComboBox.setObjectName(u'BackgroundComboBox')
self.backgroundTypeLayout.addRow(self.backgroundLabel,
self.backgroundComboBox)
- self.backgroundTypeSpacer = QtGui.QSpacerItem(10, 0,
- QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
self.backgroundTypeLayout.setItem(1, QtGui.QFormLayout.LabelRole,
- self.backgroundTypeSpacer)
+ self.spacer)
self.backgroundLayout.addLayout(self.backgroundTypeLayout)
self.backgroundStack = QtGui.QStackedLayout()
self.backgroundStack.setObjectName(u'BackgroundStack')
@@ -69,10 +69,7 @@ class Ui_ThemeWizard(object):
self.colorButton = QtGui.QPushButton(self.colorWidget)
self.colorButton.setObjectName(u'ColorButton')
self.colorLayout.addRow(self.colorLabel, self.colorButton)
- self.colorSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
- QtGui.QSizePolicy.Minimum)
- self.colorLayout.setItem(1, QtGui.QFormLayout.LabelRole,
- self.colorSpacer)
+ self.colorLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.backgroundStack.addWidget(self.colorWidget)
self.gradientWidget = QtGui.QWidget(self.backgroundPage)
self.gradientWidget.setObjectName(u'GradientWidget')
@@ -98,10 +95,7 @@ class Ui_ThemeWizard(object):
self.gradientComboBox.addItems([u'', u'', u'', u'', u''])
self.gradientLayout.addRow(self.gradientTypeLabel,
self.gradientComboBox)
- self.gradientSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
- QtGui.QSizePolicy.Minimum)
- self.gradientLayout.setItem(3, QtGui.QFormLayout.LabelRole,
- self.gradientSpacer)
+ self.gradientLayout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer)
self.backgroundStack.addWidget(self.gradientWidget)
self.imageWidget = QtGui.QWidget(self.backgroundPage)
self.imageWidget.setObjectName(u'ImageWidget')
@@ -121,10 +115,7 @@ class Ui_ThemeWizard(object):
build_icon(u':/general/general_open.png'))
self.imageFileLayout.addWidget(self.imageBrowseButton)
self.imageLayout.addRow(self.imageLabel, self.imageFileLayout)
- self.imageSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
- QtGui.QSizePolicy.Minimum)
- self.imageLayout.setItem(1, QtGui.QFormLayout.LabelRole,
- self.imageSpacer)
+ self.imageLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.backgroundStack.addWidget(self.imageWidget)
self.backgroundLayout.addLayout(self.backgroundStack)
themeWizard.addPage(self.backgroundPage)
@@ -236,6 +227,8 @@ class Ui_ThemeWizard(object):
self.footerSizeSpinBox.setObjectName(u'FooterSizeSpinBox')
self.footerAreaLayout.addRow(self.footerSizeLabel,
self.footerSizeSpinBox)
+ self.footerAreaLayout.setItem(3, QtGui.QFormLayout.LabelRole,
+ self.spacer)
themeWizard.addPage(self.footerAreaPage)
# Alignment Page
self.alignmentPage = QtGui.QWizardPage()
@@ -261,6 +254,8 @@ class Ui_ThemeWizard(object):
self.transitionsCheckBox.setObjectName(u'TransitionsCheckBox')
self.alignmentLayout.addRow(self.transitionsLabel,
self.transitionsCheckBox)
+ self.alignmentLayout.setItem(3, QtGui.QFormLayout.LabelRole,
+ self.spacer)
themeWizard.addPage(self.alignmentPage)
# Area Position Page
self.areaPositionPage = QtGui.QWizardPage()
@@ -552,16 +547,6 @@ class Ui_ThemeWizard(object):
translate('OpenLP.ThemeWizard', 'Theme name:'))
# Align all QFormLayouts towards each other.
labelWidth = max(self.backgroundLabel.minimumSizeHint().width(),
- self.colorLabel.minimumSizeHint().width(),
- self.gradientStartLabel.minimumSizeHint().width(),
- self.gradientEndLabel.minimumSizeHint().width(),
- self.gradientTypeLabel.minimumSizeHint().width(),
- self.imageLabel.minimumSizeHint().width())
- self.backgroundTypeSpacer.changeSize(labelWidth, 0,
- QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
- self.colorSpacer.changeSize(labelWidth, 0,
- QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
- self.gradientSpacer.changeSize(labelWidth, 0,
- QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
- self.imageSpacer.changeSize(labelWidth, 0,
+ self.horizontalLabel.minimumSizeHint().width())
+ self.spacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py
index 272a96f3d..93f7ead06 100644
--- a/openlp/plugins/alerts/forms/alertdialog.py
+++ b/openlp/plugins/alerts/forms/alertdialog.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_delete_push_button
class Ui_AlertDialog(object):
def setupUi(self, alertDialog):
@@ -65,9 +66,8 @@ class Ui_AlertDialog(object):
self.saveButton.setIcon(build_icon(u':/general/general_save.png'))
self.saveButton.setObjectName(u'saveButton')
self.manageButtonLayout.addWidget(self.saveButton)
- self.deleteButton = QtGui.QPushButton(alertDialog)
- self.deleteButton.setIcon(build_icon(u':/general/general_delete.png'))
- self.deleteButton.setObjectName(u'deleteButton')
+ self.deleteButton = create_delete_push_button(alertDialog)
+ self.deleteButton.setEnabled(False)
self.manageButtonLayout.addWidget(self.deleteButton)
self.manageButtonLayout.addStretch()
self.alertDialogLayout.addLayout(self.manageButtonLayout, 1, 1)
@@ -75,11 +75,13 @@ class Ui_AlertDialog(object):
self.buttonBox.addButton(QtGui.QDialogButtonBox.Close)
displayIcon = build_icon(u':/general/general_live.png')
self.displayButton = QtGui.QPushButton(alertDialog)
+ self.displayButton.setEnabled(False)
self.displayButton.setIcon(displayIcon)
self.displayButton.setObjectName(u'displayButton')
self.buttonBox.addButton(self.displayButton,
QtGui.QDialogButtonBox.ActionRole)
self.displayCloseButton = QtGui.QPushButton(alertDialog)
+ self.displayCloseButton.setEnabled(False)
self.displayCloseButton.setIcon(displayIcon)
self.displayCloseButton.setObjectName(u'displayCloseButton')
self.buttonBox.addButton(self.displayCloseButton,
@@ -101,8 +103,6 @@ class Ui_AlertDialog(object):
translate('AlertsPlugin.AlertForm', '&New'))
self.saveButton.setText(
translate('AlertsPlugin.AlertForm', '&Save'))
- self.deleteButton.setText(
- translate('AlertsPlugin.AlertForm', '&Delete'))
self.displayButton.setText(
translate('AlertsPlugin.AlertForm', 'Displ&ay'))
self.displayCloseButton.setText(
diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py
index f1a0f7fea..0639f2bb1 100644
--- a/openlp/plugins/alerts/forms/alertform.py
+++ b/openlp/plugins/alerts/forms/alertform.py
@@ -44,22 +44,22 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
self.item_id = None
QtGui.QDialog.__init__(self, plugin.formparent)
self.setupUi(self)
- QtCore.QObject.connect(self.displayButton, QtCore.SIGNAL(u'clicked()'),
- self.onDisplayClicked)
+ QtCore.QObject.connect(self.displayButton,
+ QtCore.SIGNAL(u'clicked()'), self.onDisplayClicked)
QtCore.QObject.connect(self.displayCloseButton,
QtCore.SIGNAL(u'clicked()'), self.onDisplayCloseClicked)
QtCore.QObject.connect(self.alertTextEdit,
QtCore.SIGNAL(u'textChanged(const QString&)'), self.onTextChanged)
- QtCore.QObject.connect(self.newButton, QtCore.SIGNAL(u'clicked()'),
- self.onNewClick)
- QtCore.QObject.connect(self.deleteButton, QtCore.SIGNAL(u'clicked()'),
- self.onDeleteClick)
- QtCore.QObject.connect(self.saveButton, QtCore.SIGNAL(u'clicked()'),
- self.onSaveClick)
+ QtCore.QObject.connect(self.newButton,
+ QtCore.SIGNAL(u'clicked()'), self.onNewClick)
+ QtCore.QObject.connect(self.saveButton,
+ QtCore.SIGNAL(u'clicked()'), self.onSaveClick)
QtCore.QObject.connect(self.alertListWidget,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onDoubleClick)
QtCore.QObject.connect(self.alertListWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSingleClick)
+ QtCore.QObject.connect(self.alertListWidget,
+ QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
def loadList(self):
"""
@@ -72,18 +72,15 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
item_name = QtGui.QListWidgetItem(alert.text)
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(alert.id))
self.alertListWidget.addItem(item_name)
- self.saveButton.setEnabled(False)
- self.deleteButton.setEnabled(False)
def onDisplayClicked(self):
- if self.triggerAlert(unicode(self.alertTextEdit.text())):
- self.loadList()
+ self.triggerAlert(unicode(self.alertTextEdit.text()))
def onDisplayCloseClicked(self):
if self.triggerAlert(unicode(self.alertTextEdit.text())):
self.close()
- def onDeleteClick(self):
+ def onDeleteButtonClicked(self):
"""
Deletes the selected item.
"""
@@ -95,8 +92,6 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
self.alertListWidget.takeItem(row)
self.item_id = None
self.alertTextEdit.setText(u'')
- self.saveButton.setEnabled(False)
- self.deleteButton.setEnabled(False)
def onNewClick(self):
if len(self.alertTextEdit.text()) == 0:
@@ -135,30 +130,26 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
"""
List item has been double clicked to display it
"""
- items = self.alertListWidget.selectedIndexes()
- for item in items:
- bitem = self.alertListWidget.item(item.row())
- self.triggerAlert(unicode(bitem.text()))
- self.alertTextEdit.setText(unicode(bitem.text()))
- self.item_id = (bitem.data(QtCore.Qt.UserRole)).toInt()[0]
+ item = self.alertListWidget.selectedIndexes()[0]
+ bitem = self.alertListWidget.item(item.row())
+ self.triggerAlert(unicode(bitem.text()))
+ self.alertTextEdit.setText(unicode(bitem.text()))
+ self.item_id = (bitem.data(QtCore.Qt.UserRole)).toInt()[0]
self.saveButton.setEnabled(False)
- self.deleteButton.setEnabled(True)
def onSingleClick(self):
"""
List item has been single clicked to add it to
the edit field so it can be changed.
"""
- items = self.alertListWidget.selectedIndexes()
- for item in items:
- bitem = self.alertListWidget.item(item.row())
- self.alertTextEdit.setText(unicode(bitem.text()))
- self.item_id = (bitem.data(QtCore.Qt.UserRole)).toInt()[0]
+ item = self.alertListWidget.selectedIndexes()[0]
+ bitem = self.alertListWidget.item(item.row())
+ self.alertTextEdit.setText(unicode(bitem.text()))
+ self.item_id = (bitem.data(QtCore.Qt.UserRole)).toInt()[0]
# If the alert does not contain '<>' we clear the ParameterEdit field.
if unicode(self.alertTextEdit.text()).find(u'<>') == -1:
self.parameterEdit.setText(u'')
self.saveButton.setEnabled(False)
- self.deleteButton.setEnabled(True)
def triggerAlert(self, text):
"""
@@ -167,30 +158,49 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
``text``
The alert text (unicode).
"""
- if text:
- # We found '<>' in the alert text, but the ParameterEdit field is
- # empty.
- if text.find(u'<>') != -1 and not self.parameterEdit.text() and \
- QtGui.QMessageBox.question(self,
- translate('AlertPlugin.AlertForm', 'No Parameter found'),
- translate('AlertPlugin.AlertForm', 'You have not entered a '
- 'parameter to be replaced.\nDo you want to continue anyway?'),
- QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
- QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
- self.parameterEdit.setFocus()
- return False
- # The ParameterEdit field is not empty, but we have not found '<>'
- # in the alert text.
- elif text.find(u'<>') == -1 and self.parameterEdit.text() and \
- QtGui.QMessageBox.question(self,
- translate('AlertPlugin.AlertForm', 'No Placeholder found'),
- translate('AlertPlugin.AlertForm', 'The alert text does not'
- ' contain \'<>\'.\nDo want to continue anyway?'),
- QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
- QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
- self.parameterEdit.setFocus()
- return False
- text = text.replace(u'<>', unicode(self.parameterEdit.text()))
- self.parent.alertsmanager.displayAlert(text)
- return True
- return False
+ if not text:
+ return False
+ # We found '<>' in the alert text, but the ParameterEdit field is empty.
+ if text.find(u'<>') != -1 and not self.parameterEdit.text() and \
+ QtGui.QMessageBox.question(self,
+ translate('AlertPlugin.AlertForm', 'No Parameter found'),
+ translate('AlertPlugin.AlertForm', 'You have not entered a '
+ 'parameter to be replaced.\nDo you want to continue anyway?'),
+ QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
+ QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
+ self.parameterEdit.setFocus()
+ return False
+ # The ParameterEdit field is not empty, but we have not found '<>'
+ # in the alert text.
+ elif text.find(u'<>') == -1 and self.parameterEdit.text() and \
+ QtGui.QMessageBox.question(self,
+ translate('AlertPlugin.AlertForm', 'No Placeholder found'),
+ translate('AlertPlugin.AlertForm', 'The alert text does not'
+ ' contain \'<>\'.\nDo want to continue anyway?'),
+ QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
+ QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
+ self.parameterEdit.setFocus()
+ return False
+ text = text.replace(u'<>', unicode(self.parameterEdit.text()))
+ self.parent.alertsmanager.displayAlert(text)
+ return True
+
+ def onCurrentRowChanged(self, row):
+ """
+ Called when the *alertListWidget*'s current row has been changed. This
+ enables or disables buttons which require an item to act on.
+
+ ``row``
+ The row (int). If there is no current row, the value is -1.
+ """
+ if row == -1:
+ self.displayButton.setEnabled(False)
+ self.displayCloseButton.setEnabled(False)
+ self.saveButton.setEnabled(False)
+ self.deleteButton.setEnabled(False)
+ else:
+ self.displayButton.setEnabled(True)
+ self.displayCloseButton.setEnabled(True)
+ self.deleteButton.setEnabled(True)
+ # We do not need to enable the save button, as it is only enabled
+ # when typing text in the "alertTextEdit".
diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py
index 15181e871..e3b2ad4aa 100644
--- a/openlp/plugins/bibles/bibleplugin.py
+++ b/openlp/plugins/bibles/bibleplugin.py
@@ -102,7 +102,7 @@ class BiblePlugin(Plugin):
Called to find out if the bible plugin is currently using a theme.
Returns True if the theme is being used, otherwise returns False.
"""
- if self.settings_tab.bible_theme == theme:
+ if unicode(self.settings_tab.bible_theme) == theme:
return True
return False
@@ -119,6 +119,7 @@ class BiblePlugin(Plugin):
The new name the plugin should now use.
"""
self.settings_tab.bible_theme = newTheme
+ self.settings_tab.save()
def setPluginTextStrings(self):
"""
diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py
index a2509ba97..f21dd0e07 100644
--- a/openlp/plugins/bibles/forms/bibleimportform.py
+++ b/openlp/plugins/bibles/forms/bibleimportform.py
@@ -157,10 +157,9 @@ class BibleImportForm(OpenLPWizard):
self.formatComboBox.addItems([u'', u'', u'', u'', u''])
self.formatComboBox.setObjectName(u'FormatComboBox')
self.formatLayout.addRow(self.formatLabel, self.formatComboBox)
- self.formatSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
+ self.spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Minimum)
- self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole,
- self.formatSpacer)
+ self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.selectPageLayout.addLayout(self.formatLayout)
self.selectStack = QtGui.QStackedLayout()
self.selectStack.setObjectName(u'SelectStack')
@@ -181,9 +180,7 @@ class BibleImportForm(OpenLPWizard):
self.osisBrowseButton.setObjectName(u'OsisBrowseButton')
self.osisFileLayout.addWidget(self.osisBrowseButton)
self.osisLayout.addRow(self.osisFileLabel, self.osisFileLayout)
- self.osisSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
- QtGui.QSizePolicy.Minimum)
- self.osisLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.osisSpacer)
+ self.osisLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.selectStack.addWidget(self.osisWidget)
self.csvWidget = QtGui.QWidget(self.selectPage)
self.csvWidget.setObjectName(u'CsvWidget')
@@ -226,9 +223,7 @@ class BibleImportForm(OpenLPWizard):
self.csvVersesButton.setObjectName(u'CsvVersesButton')
self.csvVersesLayout.addWidget(self.csvVersesButton)
self.csvLayout.addRow(self.csvVersesLabel, self.csvVersesLayout)
- self.csvSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
- QtGui.QSizePolicy.Minimum)
- self.csvLayout.setItem(3, QtGui.QFormLayout.LabelRole, self.csvSpacer)
+ self.csvLayout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer)
self.selectStack.addWidget(self.csvWidget)
self.openSongWidget = QtGui.QWidget(self.selectPage)
self.openSongWidget.setObjectName(u'OpenSongWidget')
@@ -248,10 +243,7 @@ class BibleImportForm(OpenLPWizard):
self.openSongFileLayout.addWidget(self.openSongBrowseButton)
self.openSongLayout.addRow(self.openSongFileLabel,
self.openSongFileLayout)
- self.openSongSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
- QtGui.QSizePolicy.Minimum)
- self.openSongLayout.setItem(1, QtGui.QFormLayout.LabelRole,
- self.openSongSpacer)
+ self.openSongLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.selectStack.addWidget(self.openSongWidget)
self.webTabWidget = QtGui.QTabWidget(self.selectPage)
self.webTabWidget.setObjectName(u'WebTabWidget')
@@ -330,10 +322,7 @@ class BibleImportForm(OpenLPWizard):
self.openlp1DisabledLabel.setWordWrap(True)
self.openlp1DisabledLabel.setObjectName(u'Openlp1DisabledLabel')
self.openlp1Layout.addRow(self.openlp1DisabledLabel)
- self.openlp1Spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
- QtGui.QSizePolicy.Minimum)
- self.openlp1Layout.setItem(1, QtGui.QFormLayout.LabelRole,
- self.openlp1Spacer)
+ self.openlp1Layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.selectStack.addWidget(self.openlp1Widget)
self.selectPageLayout.addLayout(self.selectStack)
self.addPage(self.selectPage)
@@ -401,17 +390,17 @@ class BibleImportForm(OpenLPWizard):
self.formatComboBox.setItemText(4,
translate('BiblesPlugin.ImportWizardForm', 'openlp.org 1.x'))
self.openlp1FileLabel.setText(
- translate('BiblesPlugin.ImportWizardForm', 'File location:'))
+ translate('BiblesPlugin.ImportWizardForm', 'Bible file:'))
self.osisFileLabel.setText(
- translate('BiblesPlugin.ImportWizardForm', 'File location:'))
+ translate('BiblesPlugin.ImportWizardForm', 'Bible file:'))
self.csvTestamentsLabel.setText(
- translate('BiblesPlugin.ImportWizardForm', 'Testaments location:'))
+ translate('BiblesPlugin.ImportWizardForm', 'Testaments file:'))
self.csvBooksLabel.setText(
- translate('BiblesPlugin.ImportWizardForm', 'Books location:'))
+ translate('BiblesPlugin.ImportWizardForm', 'Books file:'))
self.csvVersesLabel.setText(
- translate('BiblesPlugin.ImportWizardForm', 'Verse location:'))
+ translate('BiblesPlugin.ImportWizardForm', 'Verses file:'))
self.openSongFileLabel.setText(
- translate('BiblesPlugin.ImportWizardForm', 'Bible filename:'))
+ translate('BiblesPlugin.ImportWizardForm', 'Bible file:'))
self.webSourceLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Location:'))
self.webSourceComboBox.setItemText(0,
@@ -462,19 +451,12 @@ class BibleImportForm(OpenLPWizard):
# Align all QFormLayouts towards each other.
labelWidth = max(self.formatLabel.minimumSizeHint().width(),
self.osisFileLabel.minimumSizeHint().width(),
+ self.csvTestamentsLabel.minimumSizeHint().width(),
self.csvBooksLabel.minimumSizeHint().width(),
self.csvVersesLabel.minimumSizeHint().width(),
self.openSongFileLabel.minimumSizeHint().width(),
self.openlp1FileLabel.minimumSizeHint().width())
- self.formatSpacer.changeSize(labelWidth, 0,
- QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
- self.osisSpacer.changeSize(labelWidth, 0,
- QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
- self.csvSpacer.changeSize(labelWidth, 0,
- QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
- self.openSongSpacer.changeSize(labelWidth, 0,
- QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
- self.openlp1Spacer.changeSize(labelWidth, 0,
+ self.spacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
def validateCurrentPage(self):
diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py
index 34e1bf5a5..e6fff1cc8 100644
--- a/openlp/plugins/bibles/lib/__init__.py
+++ b/openlp/plugins/bibles/lib/__init__.py
@@ -77,9 +77,9 @@ def parse_reference(reference):
- After a verse reference all further single values are treat as verse in
the last selected chapter.
``John 3:16-18`` refers to John chapter 3 verses 16 to 18
- - After a list separator it is possible to refer to additional verses. They
- are build analog to the first ones. This way it is possible to define
- each number of verse references. It is not possible to refer to verses in
+ - After a list separator it is possible to refer to additional verses. They
+ are build analog to the first ones. This way it is possible to define each
+ number of verse references. It is not possible to refer to verses in
additional books.
``John 3:16,18`` refers to John chapter 3 verses 16 and 18
``John 3:16-18,20`` refers to John chapter 3 verses 16 to 18 and 20
@@ -91,7 +91,7 @@ def parse_reference(reference):
``range_string`` is a regular expression which matches for verse range
declarations:
- 1. ``(?:(?P[0-9]+)%(sep_v)s)?'
+ 1. ``(?:(?P[0-9]+)%(sep_v)s)?``
It starts with a optional chapter reference ``from_chapter`` followed by
a verse separator.
2. ``(?P[0-9]+)``
@@ -105,7 +105,7 @@ def parse_reference(reference):
5. ``(?P[0-9]+)``
The ``to_verse`` reference is equivalent to group 2.
- The full reference is matched against get_reference_match(u'full'). This
+ The full reference is matched against get_reference_match(u'full'). This
regular expression looks like this:
1. ``^\s*(?!\s)(?P[\d]*[^\d]+)(?(?:`` + range_string + ``(?:%(sep_l)s|(?=\s*$)))+)\s*$``
- The second group contains all ``ranges``. This can be multiple
+ The second group contains all ``ranges``. This can be multiple
declarations of a range_string separated by a list separator.
The reference list is a list of tuples, with each tuple structured like
diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py
index 8db214140..7cba6facb 100644
--- a/openlp/plugins/bibles/lib/http.py
+++ b/openlp/plugins/bibles/lib/http.py
@@ -443,7 +443,6 @@ class HTTPBible(BibleDB):
book = db_book.name
if BibleDB.get_verse_count(self, book, reference[1]) == 0:
Receiver.send_message(u'cursor_busy')
- Receiver.send_message(u'openlp_process_events')
search_results = self.get_chapter(book, reference[1])
if search_results and search_results.has_verselist():
## We have found a book of the bible lets check to see
diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py
index 26f45b6b3..c162447b2 100644
--- a/openlp/plugins/bibles/lib/mediaitem.py
+++ b/openlp/plugins/bibles/lib/mediaitem.py
@@ -30,7 +30,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \
ItemCapabilities, translate
-from openlp.core.lib.ui import critical_error_message_box, media_item_combo_box
+from openlp.core.lib.ui import 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
@@ -379,9 +380,7 @@ class BibleMediaItem(MediaManagerItem):
book_data = bibles[bible].get_books()
books = [book.name for book in book_data]
books.sort()
- completer = QtGui.QCompleter(books)
- completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
- self.quickSearchEdit.setCompleter(completer)
+ add_widget_completer(books, self.quickSearchEdit)
def onAdvancedVersionComboBox(self):
self.initialiseBible(
diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py
index 12a6562bc..9a0fd110d 100644
--- a/openlp/plugins/bibles/lib/opensong.py
+++ b/openlp/plugins/bibles/lib/opensong.py
@@ -38,7 +38,6 @@ class OpenSongBible(BibleDB):
"""
OpenSong Bible format importer class.
"""
-
def __init__(self, parent, **kwargs):
"""
Constructor to create and set up an instance of the OpenSongBible
@@ -81,14 +80,13 @@ class OpenSongBible(BibleDB):
db_book.id,
int(chapter.attrib[u'n'].split()[-1]),
int(verse.attrib[u'n']),
- unicode(verse.text)
- )
- Receiver.send_message(u'openlp_process_events')
+ unicode(verse.text))
self.wizard.incrementProgressBar(unicode(translate(
'BiblesPlugin.Opensong', 'Importing %s %s...',
'Importing ...')) %
(db_book.name, int(chapter.attrib[u'n'].split()[-1])))
- self.session.commit()
+ self.session.commit()
+ Receiver.send_message(u'openlp_process_events')
except (IOError, AttributeError):
log.exception(u'Loading bible from OpenSong file failed')
success = False
diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py
index 75717c082..b7887aa90 100644
--- a/openlp/plugins/custom/forms/editcustomdialog.py
+++ b/openlp/plugins/custom/forms/editcustomdialog.py
@@ -27,7 +27,8 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon, translate
-from openlp.core.lib.ui import save_cancel_button_box
+from openlp.core.lib.ui import create_save_cancel_button_box, \
+ create_delete_push_button, create_up_down_push_button_set
class Ui_CustomEditDialog(object):
def setupUi(self, customEditDialog):
@@ -59,22 +60,21 @@ class Ui_CustomEditDialog(object):
self.addButton.setObjectName(u'addButton')
self.buttonLayout.addWidget(self.addButton)
self.editButton = QtGui.QPushButton(customEditDialog)
+ self.editButton.setEnabled(False)
self.editButton.setObjectName(u'editButton')
self.buttonLayout.addWidget(self.editButton)
self.editAllButton = QtGui.QPushButton(customEditDialog)
self.editAllButton.setObjectName(u'editAllButton')
self.buttonLayout.addWidget(self.editAllButton)
- self.deleteButton = QtGui.QPushButton(customEditDialog)
- self.deleteButton.setObjectName(u'deleteButton')
+ self.deleteButton = create_delete_push_button(customEditDialog)
+ self.deleteButton.setEnabled(False)
self.buttonLayout.addWidget(self.deleteButton)
self.buttonLayout.addStretch()
- self.upButton = QtGui.QPushButton(customEditDialog)
- self.upButton.setIcon(build_icon(u':/services/service_up.png'))
- self.upButton.setObjectName(u'upButton')
+ self.upButton, self.downButton = create_up_down_push_button_set(
+ customEditDialog)
+ self.upButton.setEnabled(False)
+ self.downButton.setEnabled(False)
self.buttonLayout.addWidget(self.upButton)
- self.downButton = QtGui.QPushButton(customEditDialog)
- self.downButton.setIcon(build_icon(u':/services/service_down.png'))
- self.downButton.setObjectName(u'downButton')
self.buttonLayout.addWidget(self.downButton)
self.centralLayout.addLayout(self.buttonLayout)
self.dialogLayout.addLayout(self.centralLayout)
@@ -94,7 +94,10 @@ class Ui_CustomEditDialog(object):
self.creditLabel.setBuddy(self.creditEdit)
self.bottomFormLayout.addRow(self.creditLabel, self.creditEdit)
self.dialogLayout.addLayout(self.bottomFormLayout)
- self.buttonBox = save_cancel_button_box(customEditDialog)
+ self.buttonBox = create_save_cancel_button_box(customEditDialog)
+ self.previewButton = QtGui.QPushButton()
+ self.buttonBox.addButton(
+ self.previewButton, QtGui.QDialogButtonBox.ActionRole)
self.dialogLayout.addWidget(self.buttonBox)
self.retranslateUi(customEditDialog)
QtCore.QMetaObject.connectSlotsByName(customEditDialog)
@@ -102,12 +105,6 @@ class Ui_CustomEditDialog(object):
def retranslateUi(self, customEditDialog):
customEditDialog.setWindowTitle(
translate('CustomPlugin.EditCustomForm', 'Edit Custom Slides'))
- self.upButton.setToolTip(
- translate('CustomPlugin.EditCustomForm', 'Move slide up one '
- 'position.'))
- self.downButton.setToolTip(
- translate('CustomPlugin.EditCustomForm', 'Move slide down one '
- 'position.'))
self.titleLabel.setText(
translate('CustomPlugin.EditCustomForm', '&Title:'))
self.addButton.setText(
@@ -125,12 +122,9 @@ class Ui_CustomEditDialog(object):
self.editAllButton.setToolTip(
translate('CustomPlugin.EditCustomForm', 'Edit all the slides at '
'once.'))
- self.deleteButton.setText(
- translate('CustomPlugin.EditCustomForm', '&Delete'))
- self.deleteButton.setToolTip(
- translate('CustomPlugin.EditCustomForm', 'Delete the selected '
- 'slide.'))
self.themeLabel.setText(
translate('CustomPlugin.EditCustomForm', 'The&me:'))
self.creditLabel.setText(
translate('CustomPlugin.EditCustomForm', '&Credits:'))
+ self.previewButton.setText(
+ translate('CustomPlugin.EditCustomForm', 'Save && Preview'))
diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py
index e8dfa20aa..b667cd529 100644
--- a/openlp/plugins/custom/forms/editcustomform.py
+++ b/openlp/plugins/custom/forms/editcustomform.py
@@ -48,52 +48,22 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
"""
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
+ # Create other objects and forms.
+ self.manager = manager
+ self.editSlideForm = EditCustomSlideForm(self)
# Connecting signals and slots
- self.previewButton = QtGui.QPushButton()
- self.previewButton.setText(
- translate('CustomPlugin.EditCustomForm', 'Save && Preview'))
- self.buttonBox.addButton(
- self.previewButton, QtGui.QDialogButtonBox.ActionRole)
- QtCore.QObject.connect(self.buttonBox,
- QtCore.SIGNAL(u'clicked(QAbstractButton*)'), self.onPreview)
+ QtCore.QObject.connect(self.previewButton,
+ QtCore.SIGNAL(u'pressed()'), self.onPreviewButtonPressed)
QtCore.QObject.connect(self.addButton,
QtCore.SIGNAL(u'pressed()'), self.onAddButtonPressed)
QtCore.QObject.connect(self.editButton,
QtCore.SIGNAL(u'pressed()'), self.onEditButtonPressed)
QtCore.QObject.connect(self.editAllButton,
QtCore.SIGNAL(u'pressed()'), self.onEditAllButtonPressed)
- QtCore.QObject.connect(self.deleteButton,
- QtCore.SIGNAL(u'pressed()'), self.onDeleteButtonPressed)
- QtCore.QObject.connect(self.upButton,
- QtCore.SIGNAL(u'pressed()'), self.onUpButtonPressed)
- QtCore.QObject.connect(self.downButton,
- QtCore.SIGNAL(u'pressed()'), self.onDownButtonPressed)
- QtCore.QObject.connect(self.slideListView,
- QtCore.SIGNAL(u'itemClicked(QListWidgetItem*)'),
- self.onSlideListViewPressed)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'theme_update_list'), self.loadThemes)
- # Create other objects and forms.
- self.manager = manager
- self.editSlideForm = EditCustomSlideForm(self)
- self.initialise()
-
- def onPreview(self, button):
- log.debug(u'onPreview')
- if button.text() == unicode(translate('CustomPlugin.EditCustomForm',
- 'Save && Preview')) and self.saveCustom():
- Receiver.send_message(u'custom_preview')
-
- def initialise(self):
- self.addButton.setEnabled(True)
- self.deleteButton.setEnabled(False)
- self.editButton.setEnabled(False)
- self.editAllButton.setEnabled(True)
- self.titleEdit.setText(u'')
- self.creditEdit.setText(u'')
- self.slideListView.clear()
- # Make sure we have a new item.
- self.customSlide = CustomSlide()
+ QtCore.QObject.connect(self.slideListView,
+ QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
def loadThemes(self, themelist):
self.themeComboBox.clear()
@@ -112,9 +82,13 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
States whether the custom is edited while being previewed in the
preview panel.
"""
- self.customSlide = CustomSlide()
- self.initialise()
- if id != 0:
+ self.slideListView.clear()
+ if id == 0:
+ self.customSlide = CustomSlide()
+ self.titleEdit.setText(u'')
+ self.creditEdit.setText(u'')
+ self.themeComboBox.setCurrentIndex(0)
+ else:
self.customSlide = self.manager.get_object(CustomSlide, id)
self.titleEdit.setText(self.customSlide.title)
self.creditEdit.setText(self.customSlide.credits)
@@ -128,9 +102,6 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
if id == -1:
id = 0
self.themeComboBox.setCurrentIndex(id)
- else:
- self.themeComboBox.setCurrentIndex(0)
- self.editAllButton.setEnabled(False)
# If not preview hide the preview button.
self.previewButton.setVisible(False)
if preview:
@@ -150,9 +121,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
"""
Saves the custom.
"""
- valid, message = self._validate()
- if not valid:
- critical_error_message_box(message=message)
+ if not self._validate():
return False
sxml = CustomXMLBuilder()
sxml.new_document()
@@ -168,14 +137,14 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
self.customSlide.theme_name = unicode(self.themeComboBox.currentText())
return self.manager.save_object(self.customSlide)
- def onUpButtonPressed(self):
+ def onUpButtonClicked(self):
selectedRow = self.slideListView.currentRow()
if selectedRow != 0:
qw = self.slideListView.takeItem(selectedRow)
self.slideListView.insertItem(selectedRow - 1, qw)
self.slideListView.setCurrentRow(selectedRow - 1)
- def onDownButtonPressed(self):
+ def onDownButtonClicked(self):
selectedRow = self.slideListView.currentRow()
# zero base arrays
if selectedRow != self.slideListView.count() - 1:
@@ -183,16 +152,11 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
self.slideListView.insertItem(selectedRow + 1, qw)
self.slideListView.setCurrentRow(selectedRow + 1)
- def onSlideListViewPressed(self, item):
- self.deleteButton.setEnabled(True)
- self.editButton.setEnabled(True)
-
def onAddButtonPressed(self):
self.editSlideForm.setText(u'')
if self.editSlideForm.exec_():
for slide in self.editSlideForm.getText():
self.slideListView.addItem(slide)
- self.editAllButton.setEnabled(True)
def onEditButtonPressed(self):
self.editSlideForm.setText(self.slideListView.currentItem().text())
@@ -203,16 +167,23 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
"""
Edits all slides.
"""
- if self.slideListView.count() > 0:
- slide_list = u''
- for row in range(0, self.slideListView.count()):
- item = self.slideListView.item(row)
- slide_list += item.text()
- if row != self.slideListView.count() - 1:
- slide_list += u'\n[---]\n'
- self.editSlideForm.setText(slide_list)
- if self.editSlideForm.exec_():
- self.updateSlideList(self.editSlideForm.getText(), True)
+ slide_list = u''
+ for row in range(0, self.slideListView.count()):
+ item = self.slideListView.item(row)
+ slide_list += item.text()
+ if row != self.slideListView.count() - 1:
+ slide_list += u'\n[---]\n'
+ self.editSlideForm.setText(slide_list)
+ if self.editSlideForm.exec_():
+ self.updateSlideList(self.editSlideForm.getText(), True)
+
+ def onPreviewButtonPressed(self):
+ """
+ Save the custom item and preview it.
+ """
+ log.debug(u'onPreview')
+ if self.saveCustom():
+ Receiver.send_message(u'custom_preview')
def updateSlideList(self, slides, edit_all=False):
"""
@@ -243,14 +214,41 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
self.slideListView.addItem(slide)
self.slideListView.repaint()
- def onDeleteButtonPressed(self):
+ def onDeleteButtonClicked(self):
+ """
+ Removes the current row from the list.
+ """
self.slideListView.takeItem(self.slideListView.currentRow())
- self.editButton.setEnabled(True)
- self.editAllButton.setEnabled(True)
- if self.slideListView.count() == 0:
+ if self.slideListView.currentRow() == 0:
+ self.upButton.setEnabled(False)
+ if self.slideListView.currentRow() == self.slideListView.count():
+ self.downButton.setEnabled(False)
+
+ def onCurrentRowChanged(self, row):
+ """
+ Called when the *slideListView*'s current row has been changed. This
+ enables or disables buttons which require an slide to act on.
+
+ ``row``
+ The row (int). If there is no current row, the value is -1.
+ """
+ if row == -1:
self.deleteButton.setEnabled(False)
self.editButton.setEnabled(False)
- self.editAllButton.setEnabled(False)
+ self.upButton.setEnabled(False)
+ self.downButton.setEnabled(False)
+ else:
+ self.deleteButton.setEnabled(True)
+ self.editButton.setEnabled(True)
+ # Decide if the up/down buttons should be enabled or not.
+ if self.slideListView.count() - 1 == row:
+ self.downButton.setEnabled(False)
+ else:
+ self.downButton.setEnabled(True)
+ if row == 0:
+ self.upButton.setEnabled(False)
+ else:
+ self.upButton.setEnabled(True)
def _validate(self):
"""
@@ -259,10 +257,14 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
# We must have a title.
if len(self.titleEdit.displayText()) == 0:
self.titleEdit.setFocus()
- return False, translate('CustomPlugin.EditCustomForm',
- 'You need to type in a title.')
+ critical_error_message_box(
+ message=translate('CustomPlugin.EditCustomForm',
+ 'You need to type in a title.'))
+ return False
# We must have at least one slide.
if self.slideListView.count() == 0:
- return False, translate('CustomPlugin.EditCustomForm',
- 'You need to add at least one slide')
- return True, u''
+ critical_error_message_box(
+ message=translate('CustomPlugin.EditCustomForm',
+ 'You need to add at least one slide'))
+ return False
+ return True
diff --git a/openlp/plugins/custom/forms/editcustomslidedialog.py b/openlp/plugins/custom/forms/editcustomslidedialog.py
index 93bff68b8..24c40d6e6 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 save_cancel_button_box
+from openlp.core.lib.ui import create_save_cancel_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 = save_cancel_button_box(customSlideEditDialog)
+ self.buttonBox = create_save_cancel_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 ec915b0a9..908c4e18d 100644
--- a/openlp/plugins/custom/lib/mediaitem.py
+++ b/openlp/plugins/custom/lib/mediaitem.py
@@ -69,7 +69,7 @@ class CustomMediaItem(MediaManagerItem):
QtCore.SIGNAL(u'custom_preview'), self.onPreviewClick)
def initialise(self):
- self.loadCustomListView(self.manager.get_all_objects(
+ self.loadList(self.manager.get_all_objects(
CustomSlide, order_by_ref=CustomSlide.title))
# Called to redisplay the custom list screen edith from a search
# or from the exit of the Custom edit dialog. If remote editing is
@@ -80,7 +80,7 @@ class CustomMediaItem(MediaManagerItem):
self.onPreviewClick()
self.onRemoteEditClear()
- def loadCustomListView(self, list):
+ def loadList(self, list):
self.listView.clear()
for customSlide in list:
custom_name = QtGui.QListWidgetItem(customSlide.title)
diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py
index cbefc7171..71027881c 100644
--- a/openlp/plugins/images/lib/mediaitem.py
+++ b/openlp/plugins/images/lib/mediaitem.py
@@ -123,19 +123,19 @@ class ImageMediaItem(MediaManagerItem):
self.settingsSection, self.getFileList())
def loadList(self, list):
- for file in list:
- filename = os.path.split(unicode(file))[1]
+ for imageFile in list:
+ filename = os.path.split(unicode(imageFile))[1]
thumb = os.path.join(self.servicePath, filename)
if os.path.exists(thumb):
- if self.validate(file, thumb):
+ if self.validate(imageFile, thumb):
icon = build_icon(thumb)
else:
icon = build_icon(u':/general/general_delete.png')
else:
- icon = self.iconFromFile(file, thumb)
+ icon = self.iconFromFile(imageFile, thumb)
item_name = QtGui.QListWidgetItem(filename)
item_name.setIcon(icon)
- item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
+ item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(imageFile))
self.listView.addItem(item_name)
def generateSlideData(self, service_item, item=None, xmlVersion=False):
diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py
index 8afed6022..17417df58 100644
--- a/openlp/plugins/presentations/presentationplugin.py
+++ b/openlp/plugins/presentations/presentationplugin.py
@@ -74,7 +74,11 @@ class PresentationPlugin(Plugin):
self.insertToolboxItem()
for controller in self.controllers:
if self.controllers[controller].enabled():
- self.controllers[controller].start_process()
+ try:
+ self.controllers[controller].start_process()
+ except:
+ log.exception(u'Failed to start controller process')
+ self.controllers[controller].available = False
self.mediaItem.buildFileMaskString()
def finalise(self):
diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py
index 3fd3c5fef..0b3f791d1 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 save_cancel_button_box
+from openlp.core.lib.ui import create_save_cancel_button_box
class Ui_AuthorsDialog(object):
def setupUi(self, authorsDialog):
@@ -56,7 +56,8 @@ class Ui_AuthorsDialog(object):
self.displayLabel.setBuddy(self.displayEdit)
self.authorLayout.addRow(self.displayLabel, self.displayEdit)
self.dialogLayout.addLayout(self.authorLayout)
- self.dialogLayout.addWidget(save_cancel_button_box(authorsDialog))
+ self.dialogLayout.addWidget(
+ create_save_cancel_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 c44b42d46..e9be62830 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 save_cancel_button_box
+from openlp.core.lib.ui import create_save_cancel_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 = save_cancel_button_box(editSongDialog)
+ self.buttonBox = create_save_cancel_button_box(editSongDialog)
self.dialogLayout.addWidget(self.buttonBox)
self.retranslateUi(editSongDialog)
QtCore.QMetaObject.connectSlotsByName(editSongDialog)
diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py
index bf94503ff..8536d38b8 100644
--- a/openlp/plugins/songs/forms/editsongform.py
+++ b/openlp/plugins/songs/forms/editsongform.py
@@ -30,7 +30,7 @@ import re
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, translate
-from openlp.core.lib.ui import critical_error_message_box
+from openlp.core.lib.ui import add_widget_completer, critical_error_message_box
from openlp.plugins.songs.forms import EditVerseForm
from openlp.plugins.songs.lib import SongXML, VerseType
from openlp.plugins.songs.lib.db import Book, Song, Author, Topic
@@ -129,37 +129,26 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.authorsComboBox.setItemData(
row, QtCore.QVariant(author.id))
self.authors.append(author.display_name)
- completer = QtGui.QCompleter(self.authors)
- completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
- self.authorsComboBox.setCompleter(completer)
+ add_widget_completer(self.authors, self.authorsComboBox)
def loadTopics(self):
- topics = self.manager.get_all_objects(Topic, order_by_ref=Topic.name)
- self.topicsComboBox.clear()
- self.topicsComboBox.addItem(u'')
self.topics = []
- for topic in topics:
- row = self.topicsComboBox.count()
- self.topicsComboBox.addItem(topic.name)
- self.topics.append(topic.name)
- self.topicsComboBox.setItemData(row, QtCore.QVariant(topic.id))
- completer = QtGui.QCompleter(self.topics)
- completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
- self.topicsComboBox.setCompleter(completer)
+ self.__loadObjects(Topic, self.topicsComboBox, self.topics)
def loadBooks(self):
- books = self.manager.get_all_objects(Book, order_by_ref=Book.name)
- self.songBookComboBox.clear()
- self.songBookComboBox.addItem(u'')
self.books = []
- for book in books:
- row = self.songBookComboBox.count()
- self.songBookComboBox.addItem(book.name)
- self.books.append(book.name)
- self.songBookComboBox.setItemData(row, QtCore.QVariant(book.id))
- completer = QtGui.QCompleter(self.books)
- completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
- self.songBookComboBox.setCompleter(completer)
+ self.__loadObjects(Book, self.songBookComboBox, self.books)
+
+ def __loadObjects(self, cls, combo, cache):
+ objects = self.manager.get_all_objects(cls, order_by_ref=cls.name)
+ combo.clear()
+ combo.addItem(u'')
+ for object in objects:
+ row = combo.count()
+ combo.addItem(object.name)
+ cache.append(object.name)
+ combo.setItemData(row, QtCore.QVariant(object.id))
+ add_widget_completer(cache, combo)
def loadThemes(self, theme_list):
self.themeComboBox.clear()
@@ -168,9 +157,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
for theme in theme_list:
self.themeComboBox.addItem(theme)
self.themes.append(theme)
- completer = QtGui.QCompleter(self.themes)
- completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
- self.themeComboBox.setCompleter(completer)
+ add_widget_completer(self.themes, self.themeComboBox)
def newSong(self):
log.debug(u'New Song')
diff --git a/openlp/plugins/songs/forms/editversedialog.py b/openlp/plugins/songs/forms/editversedialog.py
index deaf952e2..b4bc4551f 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 save_cancel_button_box
+from openlp.core.lib.ui import create_save_cancel_button_box
from openlp.plugins.songs.lib import VerseType
class Ui_EditVerseDialog(object):
@@ -60,7 +60,8 @@ class Ui_EditVerseDialog(object):
self.verseTypeLayout.addWidget(self.insertButton)
self.verseTypeLayout.addStretch()
self.dialogLayout.addLayout(self.verseTypeLayout)
- self.dialogLayout.addWidget(save_cancel_button_box(editVerseDialog))
+ self.dialogLayout.addWidget(
+ create_save_cancel_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 fcd6bd364..89b8941b5 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 save_cancel_button_box
+from openlp.core.lib.ui import create_save_cancel_button_box
class Ui_SongBookDialog(object):
def setupUi(self, songBookDialog):
@@ -50,7 +50,8 @@ class Ui_SongBookDialog(object):
self.publisherLabel.setBuddy(self.publisherEdit)
self.bookLayout.addRow(self.publisherLabel, self.publisherEdit)
self.dialogLayout.addLayout(self.bookLayout)
- self.dialogLayout.addWidget(save_cancel_button_box(songBookDialog))
+ self.dialogLayout.addWidget(
+ create_save_cancel_button_box(songBookDialog))
self.retranslateUi(songBookDialog)
songBookDialog.setMaximumHeight(songBookDialog.sizeHint().height())
QtCore.QMetaObject.connectSlotsByName(songBookDialog)
diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py
index f1e1f82ed..a9af7f6b2 100644
--- a/openlp/plugins/songs/forms/songimportform.py
+++ b/openlp/plugins/songs/forms/songimportform.py
@@ -162,6 +162,8 @@ class SongImportForm(OpenLPWizard):
self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole,
self.formatSpacer)
self.sourceLayout.addLayout(self.formatLayout)
+ self.stackSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
+ QtGui.QSizePolicy.Expanding)
self.formatStack = QtGui.QStackedLayout()
self.formatStack.setObjectName(u'FormatStack')
# OpenLP 2.0
@@ -807,10 +809,8 @@ class SongImportForm(OpenLPWizard):
browseButton.setIcon(self.openIcon)
browseButton.setObjectName(obj_prefix + u'BrowseButton')
fileLayout.addWidget(browseButton)
- formSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
- QtGui.QSizePolicy.Expanding)
importLayout.addLayout(fileLayout)
- importLayout.addSpacerItem(formSpacer)
+ importLayout.addSpacerItem(self.stackSpacer)
else:
fileListWidget = QtGui.QListWidget(importWidget)
fileListWidget.setSelectionMode(
@@ -859,6 +859,7 @@ class SongImportForm(OpenLPWizard):
disabledLabel.setWordWrap(True)
disabledLabel.setObjectName(obj_prefix + u'DisabledLabel')
disabledLayout.addWidget(disabledLabel)
+ disabledLayout.addSpacerItem(self.stackSpacer)
layout.addWidget(disabledWidget)
importWidget = QtGui.QWidget(page)
importWidget.setObjectName(obj_prefix + u'ImportWidget')
diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py
index 737d63204..1eb63fbf4 100644
--- a/openlp/plugins/songs/forms/songmaintenanceform.py
+++ b/openlp/plugins/songs/forms/songmaintenanceform.py
@@ -372,7 +372,6 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
Utility method to merge two objects to leave one in the database.
"""
Receiver.send_message(u'cursor_busy')
- Receiver.send_message(u'openlp_process_events')
merge(dbObject)
reset()
Receiver.send_message(u'songs_load_list')
@@ -484,19 +483,19 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def onAuthorsListRowChanged(self, row):
"""
- Called when the *authorsListWidget*s current row has changed.
+ Called when the *authorsListWidget*'s current row has changed.
"""
self.__rowChange(row, self.authorsEditButton, self.authorsDeleteButton)
def onTopicsListRowChanged(self, row):
"""
- Called when the *topicsListWidget*s current row has changed.
+ Called when the *topicsListWidget*'s current row has changed.
"""
self.__rowChange(row, self.topicsEditButton, self.topicsDeleteButton)
def onBooksListRowChanged(self, row):
"""
- Called when the *booksListWidget*s current row has changed.
+ Called when the *booksListWidget*'s current row has changed.
"""
self.__rowChange(row, self.booksEditButton, self.booksDeleteButton)
diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py
index f2c9fdeba..596597034 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 save_cancel_button_box
+from openlp.core.lib.ui import create_save_cancel_button_box
class Ui_TopicsDialog(object):
def setupUi(self, topicsDialog):
@@ -44,7 +44,8 @@ class Ui_TopicsDialog(object):
self.nameLabel.setBuddy(self.nameEdit)
self.nameLayout.addRow(self.nameLabel, self.nameEdit)
self.dialogLayout.addLayout(self.nameLayout)
- self.dialogLayout.addWidget(save_cancel_button_box(topicsDialog))
+ self.dialogLayout.addWidget(
+ create_save_cancel_button_box(topicsDialog))
self.retranslateUi(topicsDialog)
topicsDialog.setMaximumHeight(topicsDialog.sizeHint().height())
QtCore.QMetaObject.connectSlotsByName(topicsDialog)
diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py
index 838172893..2bbf818b3 100644
--- a/openlp/plugins/songs/lib/db.py
+++ b/openlp/plugins/songs/lib/db.py
@@ -39,6 +39,7 @@ class Author(BaseModel):
"""
pass
+
class Book(BaseModel):
"""
Book model
@@ -47,30 +48,115 @@ class Book(BaseModel):
return u'' % (
str(self.id), self.name, self.publisher)
+
class MediaFile(BaseModel):
"""
MediaFile model
"""
pass
+
class Song(BaseModel):
"""
Song model
"""
pass
+
class Topic(BaseModel):
"""
Topic model
"""
pass
+
def init_schema(url):
+
"""
- Setup the songs database connection and initialise the database schema
+ Setup the songs database connection and initialise the database schema.
``url``
The database to setup
+
+ The song database contains the following tables:
+
+ * authors
+ * authors_songs
+ * media_files
+ * media_files_songs
+ * song_books
+ * songs
+ * songs_topics
+ * topics
+
+ **authors** Table
+ This table holds the names of all the authors. It has the following
+ columns:
+
+ * id
+ * first_name
+ * last_name
+ * display_name
+
+ **authors_songs Table**
+ This is a bridging table between the *authors* and *songs* tables, which
+ serves to create a many-to-many relationship between the two tables. It
+ has the following columns:
+
+ * author_id
+ * song_id
+
+ **media_files Table**
+ * id
+ * file_name
+ * type
+
+ **media_files_songs Table**
+ * media_file_id
+ * song_id
+
+ **song_books Table**
+ The *song_books* table holds a list of books that a congregation gets
+ their songs from, or old hymnals now no longer used. This table has the
+ following columns:
+
+ * id
+ * name
+ * publisher
+
+ **songs Table**
+ This table contains the songs, and each song has a list of attributes.
+ The *songs* table has the following columns:
+
+ * id
+ * song_book_id
+ * title
+ * alternate_title
+ * lyrics
+ * verse_order
+ * copyright
+ * comments
+ * ccli_number
+ * song_number
+ * theme_name
+ * search_title
+ * search_lyrics
+
+ **songs_topics Table**
+ This is a bridging table between the *songs* and *topics* tables, which
+ serves to create a many-to-many relationship between the two tables. It
+ has the following columns:
+
+ * song_id
+ * topic_id
+
+ **topics Table**
+ The topics table holds a selection of topics that songs can cover. This
+ is useful when a worship leader wants to select songs with a certain
+ theme. This table has the following columns:
+
+ * id
+ * name
"""
session, metadata = init_db(url)
diff --git a/resources/forms/exceptiondialog.ui b/resources/forms/exceptiondialog.ui
index f6f15cdc7..9fd138092 100644
--- a/resources/forms/exceptiondialog.ui
+++ b/resources/forms/exceptiondialog.ui
@@ -13,82 +13,128 @@
Dialog
-
-
- 8
+
+
+
+ 8
+ 194
+ 564
+ 171
+
-
- 8
+
+ true
- -
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
-
- 64
- 64
-
-
-
-
- 64
- 64
-
-
-
-
-
-
- :/graphics/exception.png
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Oops! OpenLP hit a problem, and couldn't recover. The text in the box below contains information that might be helpful to the OpenLP developers, so please e-mail it to bugs@openlp.org, along with a detailed description of what you were doing when the problem occurred.
-
-
- true
-
-
-
-
-
- -
-
-
- true
-
-
- false
-
-
-
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Close
-
-
-
-
+
+ false
+
+
+
+
+
+ 8
+ 373
+ 83
+ 26
+
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Close
+
+
+
+
+
+ 8
+ 103
+ 561
+ 71
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ 10
+ 170
+ 301
+ 17
+
+
+
+ TextLabel
+
+
+
+
+
+ 10
+ 80
+ 59
+ 17
+
+
+
+ TextLabel
+
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 64
+ 64
+
+
+
+
+ 64
+ 64
+
+
+
+
+
+
+ :/graphics/exception.png
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Oops! OpenLP hit a problem, and couldn't recover. The text in the box below contains information that might be helpful to the OpenLP developers, so please e-mail it to bugs@openlp.org, along with a detailed description of what you were doing when the problem occurred.
+
+
+ true
+
+
+
+
+
diff --git a/scripts/bible-1to2-converter.py b/scripts/bible-1to2-converter.py
deleted file mode 100755
index ebf246608..000000000
--- a/scripts/bible-1to2-converter.py
+++ /dev/null
@@ -1,308 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2010 Raoul Snyman #
-# Portions copyright (c) 2008-2010 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 #
-###############################################################################
-
-import sys
-import os
-import sqlite
-import sqlite3
-
-from optparse import OptionParser
-from traceback import format_tb as get_traceback
-
-# Some global options to be used throughout the import process
-verbose = False
-debug = False
-old_cursor = None
-new_cursor = None
-
-# SQL create statments
-create_statements = [
- (u'table "book"', u"""CREATE TABLE book (
- id INTEGER NOT NULL,
- testament_id INTEGER,
- name VARCHAR(30),
- abbreviation VARCHAR(5),
- PRIMARY KEY (id),
- FOREIGN KEY(testament_id) REFERENCES testament (id)
-)"""),
- (u'table "metadata"', u"""CREATE TABLE metadata (
- "key" VARCHAR(255) NOT NULL,
- value VARCHAR(255),
- PRIMARY KEY ("key")
-)"""),
- (u'table "testament"', u"""CREATE TABLE testament (
- id INTEGER NOT NULL,
- name VARCHAR(30),
- PRIMARY KEY (id)
-)"""),
- (u'table "verse"', u"""CREATE TABLE verse (
- id INTEGER NOT NULL,
- book_id INTEGER,
- chapter INTEGER,
- verse INTEGER,
- text TEXT,
- PRIMARY KEY (id),
- FOREIGN KEY(book_id) REFERENCES book (id)
-)"""),
- (u'index "idx_abbrev"',
- u"""CREATE INDEX idx_abbrev ON book (abbreviation, id)"""),
- (u'index "idx_chapter_verse_book',
- u"""CREATE INDEX idx_chapter_verse_book ON verse (chapter, verse, book_id, id)"""),
- (u'index "idx_chapter_verse_text"',
- u"""CREATE INDEX idx_chapter_verse_text ON verse (text, verse, book_id, id)"""),
- (u'index "idx_name"',
- u"""CREATE INDEX idx_name ON book (name, id)""")
-]
-
-def display_sql(sql, params):
- prepared_params = []
- for param in params:
- if isinstance(param, basestring):
- prepared_params.append(u'"%s"' % param)
- elif isinstance(param, (int, long)):
- prepared_params.append(u'%d' % param)
- elif isinstance(param, (float, complex)):
- prepared_params.append(u'%f' % param)
- else:
- prepared_params.append(u'"%s"' % str(param))
- for prepared_param in prepared_params:
- sql = sql.replace(u'?', prepared_param, 1)
- return sql
-
-def create_database():
- global new_cursor, create_statements
- if debug or verbose:
- print 'Creating new database:'
- else:
- print 'Creating new database...',
- for statement_type, sql_create in create_statements:
- if debug:
- print '... ', sql_create.replace('\n', ' ').replace(' ', ' ')
- elif verbose:
- print '... creating %s...' % statement_type,
- new_cursor.execute(sql_create)
- if verbose and not debug:
- print 'done.'
- if not verbose and not debug:
- print 'done.'
-
-def import_bible():
- global old_cursor, new_cursor, debug, verbose
- if debug or verbose:
- print 'Importing metadata:'
- else:
- print 'Importing metadata...',
- if debug:
- print '... SELECT "key", "value" FROM metadata'
- elif verbose:
- print '... fetching metadata from old database...',
- old_cursor.execute(u'SELECT "key", "value" FROM metadata')
- rows = old_cursor.fetchall()
- if not debug and verbose:
- print 'done.'
- for row in rows:
- key = unicode(row[0], u'cp1252')
- value = unicode(row[1], u'cp1252')
- if key == u'Permission':
- key = u'Permissions'
- sql_insert = u'INSERT INTO metadata '\
- '("key", "value") '\
- 'VALUES (?, ?)'
- sql_params = (key, value)
- if debug:
- print '...', display_sql(sql_insert, sql_params)
- elif verbose:
- print '... importing "%s"' % key
- new_cursor.execute(sql_insert, sql_params)
- if not verbose and not debug:
- print 'done.'
- if debug or verbose:
- print 'Importing testaments:'
- else:
- print 'Importing testaments...',
- if debug:
- print '... SELECT id, name FROM testament'
- elif verbose:
- print '... fetching testaments from old database...',
- old_cursor.execute(u'SELECT id, name FROM testament')
- rows = old_cursor.fetchall()
- if not debug and verbose:
- print 'done.'
- for row in rows:
- id = int(row[0])
- name = unicode(row[1], u'cp1252')
- sql_insert = u'INSERT INTO testament '\
- '(id, name) '\
- 'VALUES (?, ?)'
- sql_params = (id, name)
- if debug:
- print '...', display_sql(sql_insert, sql_params)
- elif verbose:
- print '... importing "%s"' % name
- new_cursor.execute(sql_insert, sql_params)
- if not verbose and not debug:
- print 'done.'
- if debug or verbose:
- print 'Importing books:'
- else:
- print 'Importing books...',
- if debug:
- print '... SELECT id, testament_id, name, abbreviation FROM book'
- elif verbose:
- print '... fetching books from old database...',
- old_cursor.execute(u'SELECT id, testament_id, name, abbreviation FROM book')
- rows = old_cursor.fetchall()
- if not debug and verbose:
- print 'done.'
- book_map = {}
- for row in rows:
- testament_id = int(row[1])
- name = unicode(row[2], u'cp1252')
- abbreviation = unicode(row[3], u'cp1252')
- sql_insert = u'INSERT INTO book '\
- '(id, testament_id, name, abbreviation) '\
- 'VALUES (NULL, ?, ?, ?)'
- sql_params = (testament_id, name, abbreviation)
- if debug:
- print '...', display_sql(sql_insert, sql_params)
- elif verbose:
- print '... importing "%s"' % name
- new_cursor.execute(sql_insert, sql_params)
- book_map[row[0]] = new_cursor.lastrowid
- if debug:
- print ' >>> (old) books.id =', row[0], ' (new) books.id =', book_map[row[0]]
- if not verbose and not debug:
- print 'done.'
- if debug or verbose:
- print 'Importing verses:'
- else:
- print 'Importing verses...',
- if debug:
- print '... SELECT id, book_id, chapter, verse, text || \'\' AS text FROM verse...',
- elif verbose:
- print '... fetching verses from old database...',
- old_cursor.execute(u'SELECT id, book_id, chapter, verse, text || \'\' AS text FROM verse')
- rows = old_cursor.fetchall()
- if debug or verbose:
- print 'done.'
- for row in rows:
- book_id = int(row[1])
- chapter = int(row[2])
- verse = int(row[3])
- text = unicode(row[4], u'cp1252')
- sql_insert = u'INSERT INTO verse '\
- '(id, book_id, chapter, verse, text) '\
- 'VALUES (NULL, ?, ?, ?, ?)'
- sql_params = (book_map[book_id], chapter, verse, text)
- if debug:
- print '...', display_sql(sql_insert, sql_params)
- elif verbose:
- print '... importing "%s..."' % text[:17]
- new_cursor.execute(sql_insert, sql_params)
- if not verbose and not debug:
- print 'done.'
-
-def main(old_db, new_db):
- global old_cursor, new_cursor, debug
- old_connection = None
- new_connection = None
- try:
- old_connection = sqlite.connect(old_db)
- except:
- if debug:
- errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\
- + str(sys.exc_info()[1])
- else:
- errormsg = sys.exc_info()[1]
- print 'There was a problem connecting to the old database:', errormsg
- return 1
- try:
- new_connection = sqlite3.connect(new_db)
- except:
- if debug:
- errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\
- + str(sys.exc_info()[1])
- else:
- errormsg = sys.exc_info()[1]
- print 'There was a problem creating the new database:', errormsg
- return 1
- old_cursor = old_connection.cursor()
- new_cursor = new_connection.cursor()
- try:
- create_database()
- except:
- if debug:
- errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\
- + str(sys.exc_info()[1])
- else:
- errormsg = sys.exc_info()[1]
- print 'There was a problem creating the database:', errormsg
- return 1
- try:
- import_bible()
- new_connection.commit()
- except:
- new_connection.rollback()
- if debug:
- errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\
- + str(sys.exc_info()[1])
- else:
- errormsg = sys.exc_info()[1]
- print 'There was a problem importing songs:', errormsg
- return 1
- print 'Import complete.'
-
-if __name__ == u'__main__':
- option_parser = OptionParser(usage='Usage: %prog [options] OLDDATABASE NEWDATABASE')
- option_parser.add_option('-o', '--overwrite', dest='overwrite', default=False,
- action=u'store_true', help='Overwrite database file if it already exists.')
- option_parser.add_option('-v', '--verbose', dest='verbose', default=False,
- action=u'store_true', help='Outputs additional progress data.')
- option_parser.add_option('-d', '--debug', dest='debug', default=False,
- action=u'store_true', help='Outputs raw SQL statements (overrides verbose).')
- options, arguments = option_parser.parse_args()
- if len(arguments) < 2:
- if len(arguments) == 0:
- option_parser.error('Please specify an old database and a new database.')
- else:
- option_parser.error('Please specify a new database.')
- old_db = os.path.abspath(arguments[0])
- new_db = os.path.abspath(arguments[1])
- if not os.path.isfile(old_db):
- option_parser.error('Old database file ("%s") is not a file.' % old_db)
- if not os.path.exists(old_db):
- option_parser.error('Old database file ("%s") does not exist.' % old_db)
- if os.path.exists(new_db):
- if not options.overwrite:
- option_parser.error('New database file ("%s") exists. If you want to overwrite it, specify the --overwrite option.' % new_db)
- else:
- if not os.path.isfile(new_db):
- option_parser.error('New database file ("%s") is not a file.' % new_db)
- os.unlink(new_db)
- verbose = options.verbose
- debug = options.debug
- main(old_db, new_db)
diff --git a/scripts/openlp-1to2-converter.py b/scripts/openlp-1to2-converter.py
deleted file mode 100755
index bd554aa70..000000000
--- a/scripts/openlp-1to2-converter.py
+++ /dev/null
@@ -1,323 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2010 Raoul Snyman #
-# Portions copyright (c) 2008-2010 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 #
-###############################################################################
-
-import sys
-import os
-import sqlite
-import sqlite3
-import re
-from optparse import OptionParser
-from traceback import format_tb as get_traceback
-
-# Some global options to be used throughout the import process
-dirty_chars = re.compile(r'\W ', re.UNICODE)
-verbose = False
-debug = False
-old_cursor = None
-new_cursor = None
-
-# SQL create statments
-create_statements = [
- (u'table "authors"', u"""CREATE TABLE authors (
- id INTEGER NOT NULL,
- first_name VARCHAR(128),
- last_name VARCHAR(128),
- display_name VARCHAR(255) NOT NULL,
- PRIMARY KEY (id)
-)"""),
- (u'table "song_books"', u"""CREATE TABLE song_books (
- id INTEGER NOT NULL,
- name VARCHAR(128) NOT NULL,
- publisher VARCHAR(128),
- PRIMARY KEY (id)
-)"""),
- (u'table "songs"', u"""CREATE TABLE songs (
- id INTEGER NOT NULL,
- song_book_id INTEGER,
- title VARCHAR(255) NOT NULL,
- alternate_title VARCHAR(255),
- lyrics TEXT NOT NULL,
- verse_order VARCHAR(128),
- copyright VARCHAR(255),
- comments TEXT,
- ccli_number VARCHAR(64),
- song_number VARCHAR(64),
- theme_name VARCHAR(128),
- search_title VARCHAR(255) NOT NULL,
- search_lyrics TEXT NOT NULL,
- PRIMARY KEY (id),
- FOREIGN KEY(song_book_id) REFERENCES song_books (id)
-)"""),
- (u'table "topics"', u"""CREATE TABLE topics (
- id INTEGER NOT NULL,
- name VARCHAR(128) NOT NULL,
- PRIMARY KEY (id)
-)"""),
- (u'index "ix_songs_search_lyrics"',
- u"""CREATE INDEX ix_songs_search_lyrics ON songs (search_lyrics)"""),
- (u'index "ix_songs_search_title',
- u"""CREATE INDEX ix_songs_search_title ON songs (search_title)"""),
- (u'table "authors_songs"', u"""CREATE TABLE authors_songs (
- author_id INTEGER NOT NULL,
- song_id INTEGER NOT NULL,
- PRIMARY KEY (author_id, song_id),
- FOREIGN KEY(author_id) REFERENCES authors (id),
- FOREIGN KEY(song_id) REFERENCES songs (id)
-)"""),
- (u'table "songs_topics"', u"""CREATE TABLE songs_topics (
- song_id INTEGER NOT NULL,
- topic_id INTEGER NOT NULL,
- PRIMARY KEY (song_id, topic_id),
- FOREIGN KEY(song_id) REFERENCES songs (id),
- FOREIGN KEY(topic_id) REFERENCES topics (id)
-)""")
-]
-
-def prepare_string(dirty):
- return dirty_chars.sub(u'', dirty.replace(u'\r\n', u' ').replace(u'\n', u' '))
-
-def display_sql(sql, params):
- prepared_params = []
- for param in params:
- if isinstance(param, basestring):
- prepared_params.append(u'"%s"' % param)
- elif isinstance(param, (int, long)):
- prepared_params.append(u'%d' % param)
- elif isinstance(param, (float, complex)):
- prepared_params.append(u'%f' % param)
- else:
- prepared_params.append(u'"%s"' % str(param))
- for prepared_param in prepared_params:
- sql = sql.replace(u'?', prepared_param, 1)
- return sql
-
-def create_database():
- global new_cursor, create_statements
- if debug or verbose:
- print 'Creating new database:'
- else:
- print 'Creating new database...',
- for statement_type, sql_create in create_statements:
- if debug:
- print '... ', sql_create.replace('\n', ' ').replace(' ', ' ')
- elif verbose:
- print '... creating %s...' % statement_type,
- new_cursor.execute(sql_create)
- if verbose and not debug:
- print 'done.'
- if not verbose and not debug:
- print 'done.'
-
-def import_songs():
- global old_cursor, new_cursor, debug, verbose
- if debug or verbose:
- print 'Importing authors:'
- else:
- print 'Importing authors...',
- if debug:
- print '... SELECT authorid AS id, authorname AS displayname FROM authors'
- elif verbose:
- print '... fetching authors from old database...',
- old_cursor.execute(u'SELECT authorid AS id, authorname AS displayname FROM authors')
- rows = old_cursor.fetchall()
- if not debug and verbose:
- print 'done.'
- author_map = {}
- for row in rows:
- display_name = unicode(row[1], u'cp1252')
- names = display_name.split(u' ')
- first_name = names[0]
- last_name = u' '.join(names[1:])
- if last_name is None:
- last_name = u''
- sql_insert = u'INSERT INTO authors '\
- '(id, first_name, last_name, display_name) '\
- 'VALUES (NULL, ?, ?, ?)'
- sql_params = (first_name, last_name, display_name)
- if debug:
- print '...', display_sql(sql_insert, sql_params)
- elif verbose:
- print '... importing "%s"' % display_name
- new_cursor.execute(sql_insert, sql_params)
- author_map[row[0]] = new_cursor.lastrowid
- if debug:
- print ' >>> authors.authorid =', row[0], 'authors.id =', author_map[row[0]]
- if not verbose and not debug:
- print 'done.'
- if debug or verbose:
- print 'Importing songs:'
- else:
- print 'Importing songs...',
- if debug:
- print '... SELECT songid AS id, songtitle AS title, lyrics || \'\' AS lyrics, copyrightinfo AS copyright FROM songs...',
- elif verbose:
- print '... fetching songs from old database...',
- old_cursor.execute(u'SELECT songid AS id, songtitle AS title, lyrics || \'\' AS lyrics, copyrightinfo AS copyright FROM songs')
- rows = old_cursor.fetchall()
- if debug or verbose:
- print 'done.'
- song_map = {}
- xml_lyrics_template = u'%s'
- xml_verse_template = u''
- for row in rows:
- clean_title = unicode(row[1], u'cp1252')
- clean_lyrics = unicode(row[2], u'cp1252').replace(u'\r\n', u'\n')
- clean_copyright = unicode(row[3], u'cp1252')
- verse_order = u''
- text_lyrics = clean_lyrics.split(u'\n\n')
- xml_verse = u''
- verses = []
- for line, verse in enumerate(text_lyrics):
- if not verse:
- continue
- xml_verse += (xml_verse_template % (line + 1, verse))
- verses.append(u'V%d' % (line + 1))
- verse_order = u' '.join(verses)
- xml_lyrics = xml_lyrics_template % xml_verse
- search_title = prepare_string(clean_title)
- search_lyrics = prepare_string(clean_lyrics)
- sql_insert = u'INSERT INTO songs '\
- '(id, song_book_id, title, lyrics, verse_order, copyright, search_title, search_lyrics) '\
- 'VALUES (NULL, 0, ?, ?, ?, ?, ?, ?)'
- sql_params = (clean_title, xml_lyrics, verse_order, clean_copyright, search_title, search_lyrics)
- if debug:
- print '...', display_sql(sql_insert, (sql_params[0], u'%s...' % clean_lyrics[:7], sql_params[2], sql_params[3], sql_params[4], u'%s...' % search_lyrics[:7]))
- elif verbose:
- print '... importing "%s"' % clean_title
- new_cursor.execute(sql_insert, sql_params)
- song_map[row[0]] = new_cursor.lastrowid
- if debug:
- print ' >>> songs.songid =', row[0], 'songs.id =', song_map[row[0]]
- if not verbose and not debug:
- print 'done.'
- if debug or verbose:
- print 'Importing song-to-author mapping:'
- else:
- print 'Importing song-to-author mapping...',
- if debug:
- print '... SELECT authorid AS author_id, songid AS song_id FROM songauthors'
- elif verbose:
- print '... fetching song-to-author mapping from old database...',
- old_cursor.execute(u'SELECT authorid AS author_id, songid AS song_id FROM songauthors')
- rows = old_cursor.fetchall()
- if not debug and verbose:
- print 'done.'
- for row in rows:
- sql_insert = u'INSERT INTO authors_songs '\
- '(author_id, song_id) '\
- 'VALUES (?, ?)'
- sql_params = (author_map[row[0]], song_map[row[1]])
- if debug:
- print '... ', display_sql(sql_insert, sql_params)
- elif verbose:
- print '... Author %d (was %d) => Song %d (was %d)'\
- % (int(row[0]), author_map[row[0]],
- int(row[1]), song_map[row[1]])
- new_cursor.execute(sql_insert, sql_params)
- if not verbose and not debug:
- print 'done.'
-
-def main(old_db, new_db):
- global old_cursor, new_cursor, debug
- old_connection = None
- new_connection = None
- try:
- old_connection = sqlite.connect(old_db)
- except:
- if debug:
- errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\
- + str(sys.exc_info()[1])
- else:
- errormsg = sys.exc_info()[1]
- print 'There was a problem connecting to the old database:', errormsg
- return 1
- try:
- new_connection = sqlite3.connect(new_db)
- except:
- if debug:
- errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\
- + str(sys.exc_info()[1])
- else:
- errormsg = sys.exc_info()[1]
- print 'There was a problem creating the new database:', errormsg
- return 1
- old_cursor = old_connection.cursor()
- new_cursor = new_connection.cursor()
- try:
- create_database()
- except:
- if debug:
- errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\
- + str(sys.exc_info()[1])
- else:
- errormsg = sys.exc_info()[1]
- print 'There was a problem creating the database:', errormsg
- return 1
- try:
- import_songs()
- new_connection.commit()
- except:
- new_connection.rollback()
- if debug:
- errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\
- + str(sys.exc_info()[1])
- else:
- errormsg = sys.exc_info()[1]
- print 'There was a problem importing songs:', errormsg
- return 1
- print 'Import complete.'
-
-if __name__ == u'__main__':
- option_parser = OptionParser(usage='Usage: %prog [options] OLDDATABASE NEWDATABASE')
- option_parser.add_option('-o', '--overwrite', dest='overwrite', default=False,
- action=u'store_true', help='Overwrite database file if it already exists.')
- option_parser.add_option('-v', '--verbose', dest='verbose', default=False,
- action=u'store_true', help='Outputs additional progress data.')
- option_parser.add_option('-d', '--debug', dest='debug', default=False,
- action=u'store_true', help='Outputs raw SQL statements (overrides verbose).')
- options, arguments = option_parser.parse_args()
- if len(arguments) < 2:
- if len(arguments) == 0:
- option_parser.error('Please specify an old database and a new database.')
- else:
- option_parser.error('Please specify a new database.')
- old_db = os.path.abspath(arguments[0])
- new_db = os.path.abspath(arguments[1])
- if not os.path.isfile(old_db):
- option_parser.error('Old database file ("%s") is not a file.' % old_db)
- if not os.path.exists(old_db):
- option_parser.error('Old database file ("%s") does not exist.' % old_db)
- if os.path.exists(new_db):
- if not options.overwrite:
- option_parser.error('New database file ("%s") exists. If you want to overwrite it, specify the --overwrite option.' % new_db)
- else:
- if not os.path.isfile(new_db):
- option_parser.error('New database file ("%s") is not a file.' % new_db)
- os.unlink(new_db)
- verbose = options.verbose
- debug = options.debug
- main(old_db, new_db)
diff --git a/setup.py b/setup.py
index a435c5496..205688f1e 100755
--- a/setup.py
+++ b/setup.py
@@ -69,8 +69,7 @@ OpenLP (previously openlp.org) is free church presentation software, or lyrics p
url='http://openlp.org/',
license='GNU General Public License',
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
- scripts=['openlp.pyw', 'scripts/openlp-1to2-converter.py',
- 'scripts/bible-1to2-converter.py','scripts/openlp-remoteclient.py'],
+ scripts=['openlp.pyw', 'scripts/openlp-remoteclient.py'],
include_package_data=True,
zip_safe=False,
install_requires=[