diff --git a/.bzrignore b/.bzrignore
index f149d97a7..b91d4fc93 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -2,6 +2,7 @@
*.*~
\#*\#
*.eric4project
+*.eric5project
*.ropeproject
*.e4*
.eric4project
diff --git a/openlp/__init__.py b/openlp/__init__.py
index ac5f063d4..98e847979 100644
--- a/openlp/__init__.py
+++ b/openlp/__init__.py
@@ -30,7 +30,6 @@
The :mod:`openlp` module contains all the project produced OpenLP functionality
"""
-import openlp.core
-import openlp.plugins
+from openlp import core, plugins
__all__ = ['core', 'plugins']
diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py
index 8a8e6eef3..22207dec4 100644
--- a/openlp/core/common/__init__.py
+++ b/openlp/core/common/__init__.py
@@ -38,7 +38,7 @@ import traceback
from PyQt4 import QtCore
-log = logging.getLogger(__name__+'.__init__')
+log = logging.getLogger(__name__ + '.__init__')
FIRST_CAMEL_REGEX = re.compile('(.)([A-Z][a-z]+)')
@@ -76,6 +76,9 @@ def check_directory_exists(directory, do_not_log=False):
def get_frozen_path(frozen_option, non_frozen_option):
"""
Return a path based on the system status.
+
+ :param frozen_option:
+ :param non_frozen_option:
"""
if hasattr(sys, 'frozen') and sys.frozen == 1:
return frozen_option
diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py
index e6b7f4fe3..9561baff4 100644
--- a/openlp/core/lib/__init__.py
+++ b/openlp/core/lib/__init__.py
@@ -39,7 +39,7 @@ from PyQt4 import QtCore, QtGui, Qt
from openlp.core.common import translate
-log = logging.getLogger(__name__+'.__init__')
+log = logging.getLogger(__name__ + '.__init__')
class ServiceItemContext(object):
diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py
index 13d4b0bbb..4d7676ad6 100644
--- a/openlp/core/lib/mediamanageritem.py
+++ b/openlp/core/lib/mediamanageritem.py
@@ -168,29 +168,29 @@ class MediaManagerItem(QtGui.QWidget, RegistryProperties):
Create buttons for the media item toolbar
"""
toolbar_actions = []
- ## Import Button ##
+ # Import Button
if self.has_import_icon:
toolbar_actions.append(['Import', StringContent.Import,
':/general/general_import.png', self.on_import_click])
- ## Load Button ##
+ # Load Button
if self.has_file_icon:
toolbar_actions.append(['Load', StringContent.Load, ':/general/general_open.png', self.on_file_click])
- ## New Button ##
+ # New Button
if self.has_new_icon:
toolbar_actions.append(['New', StringContent.New, ':/general/general_new.png', self.on_new_click])
- ## Edit Button ##
+ # Edit Button
if self.has_edit_icon:
toolbar_actions.append(['Edit', StringContent.Edit, ':/general/general_edit.png', self.on_edit_click])
- ## Delete Button ##
+ # Delete Button
if self.has_delete_icon:
toolbar_actions.append(['Delete', StringContent.Delete,
':/general/general_delete.png', self.on_delete_click])
- ## Preview ##
+ # Preview
toolbar_actions.append(['Preview', StringContent.Preview,
':/general/general_preview.png', self.on_preview_click])
- ## Live Button ##
+ # Live Button
toolbar_actions.append(['Live', StringContent.Live, ':/general/general_live.png', self.on_live_click])
- ## Add to service Button ##
+ # Add to service Button
toolbar_actions.append(['Service', StringContent.Service, ':/general/general_add.png', self.on_add_click])
for action in toolbar_actions:
if action[0] == StringContent.Preview:
diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py
index e14fe8bb0..1f459524c 100644
--- a/openlp/core/lib/plugin.py
+++ b/openlp/core/lib/plugin.py
@@ -101,7 +101,7 @@ class Plugin(QtCore.QObject, RegistryProperties):
``add_import_menu_item(import_menu)``
Add an item to the Import menu.
- ``add_export_menu_Item(export_menu)``
+ ``add_export_menu_item(export_menu)``
Add an item to the Export menu.
``create_settings_tab()``
@@ -226,7 +226,7 @@ class Plugin(QtCore.QObject, RegistryProperties):
"""
pass
- def add_export_menu_Item(self, export_menu):
+ def add_export_menu_item(self, export_menu):
"""
Create a menu item and add it to the "Export" menu.
@@ -329,22 +329,24 @@ class Plugin(QtCore.QObject, RegistryProperties):
def set_plugin_ui_text_strings(self, tooltips):
"""
Called to define all translatable texts of the plugin
+
+ :param tooltips:
"""
- ## Load Action ##
+ # Load Action
self.__set_name_text_string(StringContent.Load, UiStrings().Load, tooltips['load'])
- ## Import Action ##
+ # Import Action
self.__set_name_text_string(StringContent.Import, UiStrings().Import, tooltips['import'])
- ## New Action ##
+ # New Action
self.__set_name_text_string(StringContent.New, UiStrings().Add, tooltips['new'])
- ## Edit Action ##
+ # Edit Action
self.__set_name_text_string(StringContent.Edit, UiStrings().Edit, tooltips['edit'])
- ## Delete Action ##
+ # Delete Action
self.__set_name_text_string(StringContent.Delete, UiStrings().Delete, tooltips['delete'])
- ## Preview Action ##
+ # Preview Action
self.__set_name_text_string(StringContent.Preview, UiStrings().Preview, tooltips['preview'])
- ## Send Live Action ##
+ # Send Live Action
self.__set_name_text_string(StringContent.Live, UiStrings().Live, tooltips['live'])
- ## Add to Service Action ##
+ # Add to Service Action
self.__set_name_text_string(StringContent.Service, UiStrings().Service, tooltips['service'])
def __set_name_text_string(self, name, title, tooltip):
diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py
index d24f07eac..474113c98 100644
--- a/openlp/core/lib/pluginmanager.py
+++ b/openlp/core/lib/pluginmanager.py
@@ -161,7 +161,7 @@ class PluginManager(RegistryMixin, OpenLPMixin, RegistryProperties):
"""
for plugin in self.plugins:
if plugin.status is not PluginStatus.Disabled:
- plugin.add_export_menu_Item(self.main_window.file_export_menu)
+ plugin.add_export_menu_item(self.main_window.file_export_menu)
def hook_tools_menu(self):
"""
diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py
index 6d07e1c34..17d11ef63 100644
--- a/openlp/core/lib/serviceitem.py
+++ b/openlp/core/lib/serviceitem.py
@@ -108,6 +108,9 @@ class ItemCapabilities(object):
``CanAutoStartForLive``
The capability to ignore the do not play if display blank flag.
+ ``CanEditTitle``
+ The capability to edit the title of the item
+
"""
CanPreview = 1
CanEdit = 2
@@ -125,6 +128,7 @@ class ItemCapabilities(object):
CanWordSplit = 14
HasBackgroundAudio = 15
CanAutoStartForLive = 16
+ CanEditTitle = 17
class ServiceItem(RegistryProperties):
@@ -383,7 +387,7 @@ class ServiceItem(RegistryProperties):
self.will_auto_start = header.get('will_auto_start', False)
self.processor = header.get('processor', None)
self.has_original_files = True
- #TODO Remove me in 2,3 build phase
+ # TODO: Remove me in 2,3 build phase
if self.is_capable(ItemCapabilities.HasDetailedTitleDisplay):
self.capabilities.remove(ItemCapabilities.HasDetailedTitleDisplay)
self.processor = self.title
@@ -423,7 +427,7 @@ class ServiceItem(RegistryProperties):
"""
Returns the title of the service item.
"""
- if self.is_text():
+ if self.is_text() or ItemCapabilities.CanEditTitle in self.capabilities:
return self.title
else:
if len(self._raw_frames) > 1:
diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py
index 3126d1a56..965adb053 100644
--- a/openlp/core/lib/ui.py
+++ b/openlp/core/lib/ui.py
@@ -173,7 +173,7 @@ def create_button(parent, name, **kwargs):
kwargs.setdefault('tooltip', translate('OpenLP.Ui', 'Move selection down one position.'))
else:
log.warn('The role "%s" is not defined in create_push_button().', role)
- if kwargs.pop('class', '') == 'toolbutton':
+ if kwargs.pop('btn_class', '') == 'toolbutton':
button = QtGui.QToolButton(parent)
else:
button = QtGui.QPushButton(parent)
diff --git a/openlp/core/ui/exceptiondialog.py b/openlp/core/ui/exceptiondialog.py
index 4d7abe708..212fee4cd 100644
--- a/openlp/core/ui/exceptiondialog.py
+++ b/openlp/core/ui/exceptiondialog.py
@@ -95,15 +95,15 @@ class Ui_ExceptionDialog(object):
Translate the widgets on the fly.
"""
exception_dialog.setWindowTitle(translate('OpenLP.ExceptionDialog', 'Error Occurred'))
- self.description_explanation.setText(translate('OpenLP.ExceptionDialog',
- 'Please enter a description of what you were doing to cause this error '
- '\n(Minimum 20 characters)'))
- self.message_label.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 '
- 'developers, so please e-mail it to bugs@openlp.org, along with a '
- 'detailed description of what you were doing when the problem '
- 'occurred.'))
+ self.description_explanation.setText(
+ translate('OpenLP.ExceptionDialog', 'Please enter a description of what you were doing to cause this error '
+ '\n(Minimum 20 characters)'))
+ self.message_label.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 '
+ 'developers, so please e-mail it to bugs@openlp.org, along with a '
+ 'detailed description of what you were doing when the problem '
+ 'occurred.'))
self.send_report_button.setText(translate('OpenLP.ExceptionDialog', 'Send E-Mail'))
self.save_report_button.setText(translate('OpenLP.ExceptionDialog', 'Save to File'))
self.attach_tile_button.setText(translate('OpenLP.ExceptionDialog', 'Attach File'))
diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py
index aa89da6c0..f1b875e6b 100644
--- a/openlp/core/ui/firsttimeform.py
+++ b/openlp/core/ui/firsttimeform.py
@@ -67,7 +67,7 @@ class ThemeScreenshotThread(QtCore.QThread):
title = config.get('theme_%s' % theme, 'title')
filename = config.get('theme_%s' % theme, 'filename')
screenshot = config.get('theme_%s' % theme, 'screenshot')
- urllib.request.urlretrieve('%s%s' % (self.parent().web, screenshot),
+ urllib.request.urlretrieve('%s%s' % (self.parent().themes_url, screenshot),
os.path.join(gettempdir(), 'openlp', screenshot))
item = QtGui.QListWidgetItem(title, self.parent().themes_list_widget)
item.setData(QtCore.Qt.UserRole, filename)
@@ -96,6 +96,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
if self.web_access:
files = self.web_access.read()
self.config.read_string(files.decode())
+ self.web = self.config.get('general', 'base url')
+ self.songs_url = self.web + self.config.get('songs', 'directory') + '/'
+ self.bibles_url = self.web + self.config.get('bibles', 'directory') + '/'
+ self.themes_url = self.web + self.config.get('themes', 'directory') + '/'
self.update_screen_list_combo()
self.was_download_cancelled = False
self.theme_screenshot_thread = None
@@ -341,7 +345,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
item = self.songs_list_widget.item(i)
if item.checkState() == QtCore.Qt.Checked:
filename = item.data(QtCore.Qt.UserRole)
- size = self._get_file_size('%s%s' % (self.web, filename))
+ size = self._get_file_size('%s%s' % (self.songs_url, filename))
self.max_progress += size
# Loop through the Bibles list and increase for each selected item
iterator = QtGui.QTreeWidgetItemIterator(self.bibles_tree_widget)
@@ -350,7 +354,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
item = iterator.value()
if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
filename = item.data(0, QtCore.Qt.UserRole)
- size = self._get_file_size('%s%s' % (self.web, filename))
+ size = self._get_file_size('%s%s' % (self.bibles_url, filename))
self.max_progress += size
iterator += 1
# Loop through the themes list and increase for each selected item
@@ -359,7 +363,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
item = self.themes_list_widget.item(i)
if item.checkState() == QtCore.Qt.Checked:
filename = item.data(QtCore.Qt.UserRole)
- size = self._get_file_size('%s%s' % (self.web, filename))
+ size = self._get_file_size('%s%s' % (self.themes_url, filename))
self.max_progress += size
if self.max_progress:
# Add on 2 for plugins status setting plus a "finished" point.
@@ -435,7 +439,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
self._increment_progress_bar(self.downloading % filename, 0)
self.previous_size = 0
destination = os.path.join(songs_destination, str(filename))
- self.url_get_file('%s%s' % (self.web, filename), destination)
+ self.url_get_file('%s%s' % (self.songs_url, filename), destination)
# Download Bibles
bibles_iterator = QtGui.QTreeWidgetItemIterator(
self.bibles_tree_widget)
@@ -445,7 +449,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
bible = item.data(0, QtCore.Qt.UserRole)
self._increment_progress_bar(self.downloading % bible, 0)
self.previous_size = 0
- self.url_get_file('%s%s' % (self.web, bible), os.path.join(bibles_destination, bible))
+ self.url_get_file('%s%s' % (self.bibles_url, bible), os.path.join(bibles_destination, bible))
bibles_iterator += 1
# Download themes
for i in range(self.themes_list_widget.count()):
@@ -454,7 +458,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
theme = item.data(QtCore.Qt.UserRole)
self._increment_progress_bar(self.downloading % theme, 0)
self.previous_size = 0
- self.url_get_file('%s%s' % (self.web, theme), os.path.join(themes_destination, theme))
+ self.url_get_file('%s%s' % (self.themes_url, theme), os.path.join(themes_destination, theme))
# Set Default Display
if self.display_combo_box.currentIndex() != -1:
Settings().setValue('core/monitor', self.display_combo_box.currentIndex())
diff --git a/openlp/core/ui/firsttimewizard.py b/openlp/core/ui/firsttimewizard.py
index 407842c48..1a270f931 100644
--- a/openlp/core/ui/firsttimewizard.py
+++ b/openlp/core/ui/firsttimewizard.py
@@ -211,9 +211,9 @@ class Ui_FirstTimeWizard(object):
first_time_wizard.setWindowTitle(translate('OpenLP.FirstTimeWizard', 'First Time Wizard'))
self.title_label.setText('%s' %
translate('OpenLP.FirstTimeWizard', 'Welcome to the First Time Wizard'))
- self.information_label.setText(translate('OpenLP.FirstTimeWizard',
- 'This wizard will help you to configure OpenLP for initial use. '
- 'Click the next button below to start.'))
+ self.information_label.setText(
+ translate('OpenLP.FirstTimeWizard', 'This wizard will help you to configure OpenLP for initial use. '
+ 'Click the next button below to start.'))
self.plugin_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Activate required Plugins'))
self.plugin_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Select the Plugins you wish to use. '))
self.songs_check_box.setText(translate('OpenLP.FirstTimeWizard', 'Songs'))
diff --git a/openlp/core/ui/formattingtagform.py b/openlp/core/ui/formattingtagform.py
index b7153429d..be4247bc1 100644
--- a/openlp/core/ui/formattingtagform.py
+++ b/openlp/core/ui/formattingtagform.py
@@ -63,7 +63,6 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog, FormattingTagCont
self.services = FormattingTagController()
self.tag_table_widget.itemSelectionChanged.connect(self.on_row_selected)
self.new_button.clicked.connect(self.on_new_clicked)
- #self.save_button.clicked.connect(self.on_saved_clicked)
self.delete_button.clicked.connect(self.on_delete_clicked)
self.tag_table_widget.currentCellChanged.connect(self.on_current_cell_changed)
self.button_box.rejected.connect(self.close)
@@ -202,5 +201,4 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog, FormattingTagCont
if errors:
QtGui.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), errors,
QtGui.QMessageBox.Ok)
- #self.tag_table_widget.selectRow(pre_row - 1)
self.tag_table_widget.resizeRowsToContents()
diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py
index b9423046e..946299aca 100644
--- a/openlp/core/ui/maindisplay.py
+++ b/openlp/core/ui/maindisplay.py
@@ -168,8 +168,10 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties):
"""
if enabled:
self.setAutoFillBackground(False)
+ self.setStyleSheet("QGraphicsView {background: transparent; border: 0px;}")
else:
self.setAttribute(QtCore.Qt.WA_NoSystemBackground, False)
+ self.setStyleSheet("QGraphicsView {}")
self.setAttribute(QtCore.Qt.WA_TranslucentBackground, enabled)
self.repaint()
@@ -350,7 +352,6 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties):
self.hide_display(self.hide_mode)
# Only continue if the visibility wasn't changed during method call.
elif was_visible == self.isVisible():
-
# Single screen active
if self.screens.display_count == 1:
# Only make visible if setting enabled.
diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py
index 42572484b..81e822c16 100644
--- a/openlp/core/ui/mainwindow.py
+++ b/openlp/core/ui/mainwindow.py
@@ -56,29 +56,27 @@ from openlp.core.ui.firsttimeform import FirstTimeForm
log = logging.getLogger(__name__)
MEDIA_MANAGER_STYLE = """
- QToolBox {
+QToolBox {
padding-bottom: 2px;
- }
- QToolBox::tab {
+}
+QToolBox::tab {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 palette(button), stop: 0.5 palette(button),
- stop: 1.0 palette(mid));
- border: 1px groove palette(mid);
- border-radius: 5px;
- }
- QToolBox::tab:selected {
+ stop: 0 palette(button), stop: 1.0 palette(mid));
+ border: 1px solid palette(mid);
+ border-radius: 3px;
+}
+QToolBox::tab:selected {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 palette(light), stop: 0.5 palette(midlight),
- stop: 1.0 palette(dark));
- border: 1px groove palette(dark);
+ stop: 0 palette(light), stop: 1.0 palette(button));
+ border: 1px solid palette(mid);
font-weight: bold;
- }
+}
"""
PROGRESSBAR_STYLE = """
- QProgressBar{
- height: 10px;
- }
+QProgressBar{
+ height: 10px;
+}
"""
@@ -369,7 +367,7 @@ class Ui_MainWindow(object):
self.settings_menu.setTitle(translate('OpenLP.MainWindow', '&Settings'))
self.settings_language_menu.setTitle(translate('OpenLP.MainWindow', '&Language'))
self.help_menu.setTitle(translate('OpenLP.MainWindow', '&Help'))
- self.media_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Media Manager'))
+ self.media_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Library'))
self.service_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Service Manager'))
self.theme_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Theme Manager'))
self.file_new_item.setText(translate('OpenLP.MainWindow', '&New'))
@@ -396,12 +394,12 @@ class Ui_MainWindow(object):
self.settings_shortcuts_item.setText(translate('OpenLP.MainWindow', 'Configure &Shortcuts...'))
self.formatting_tag_item.setText(translate('OpenLP.MainWindow', 'Configure &Formatting Tags...'))
self.settings_configure_item.setText(translate('OpenLP.MainWindow', '&Configure OpenLP...'))
- self.settings_export_item.setStatusTip(translate('OpenLP.MainWindow',
- 'Export OpenLP settings to a specified *.config file'))
+ self.settings_export_item.setStatusTip(
+ translate('OpenLP.MainWindow', 'Export OpenLP settings to a specified *.config file'))
self.settings_export_item.setText(translate('OpenLP.MainWindow', 'Settings'))
- self.settings_import_item.setStatusTip(translate('OpenLP.MainWindow',
- 'Import OpenLP settings from a specified *.config file previously '
- 'exported on this or another machine'))
+ self.settings_import_item.setStatusTip(
+ translate('OpenLP.MainWindow', 'Import OpenLP settings from a specified *.config file previously '
+ 'exported on this or another machine'))
self.settings_import_item.setText(translate('OpenLP.MainWindow', 'Settings'))
self.view_media_manager_item.setText(translate('OpenLP.MainWindow', '&Media Manager'))
self.view_media_manager_item.setToolTip(translate('OpenLP.MainWindow', 'Toggle Media Manager'))
@@ -598,13 +596,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties):
self.live_controller.display.setFocus()
self.activateWindow()
if self.arguments:
- args = []
- for a in self.arguments:
- args.extend([a])
- filename = args[0]
- if not isinstance(filename, str):
- filename = str(filename, sys.getfilesystemencoding())
- self.service_manager_contents.load_file(filename)
+ self.open_cmd_line_files()
elif Settings().value(self.general_settings_section + '/auto open'):
self.service_manager_contents.load_Last_file()
self.timer_version_id = self.startTimer(1000)
@@ -868,7 +860,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties):
section = 'general'
section_key = section + "/" + key
# Make sure it's a valid section for us.
- if not section in setting_sections:
+ if section not in setting_sections:
continue
# We have a good file, import it.
for section_key in import_keys:
@@ -1364,3 +1356,17 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties):
if self.new_data_path == AppLocation.get_directory(AppLocation.DataDir):
settings.remove('advanced/data path')
self.application.set_normal_cursor()
+
+ def open_cmd_line_files(self):
+ """
+ Open files passed in through command line arguments
+ """
+ args = []
+ for a in self.arguments:
+ args.extend([a])
+ for arg in args:
+ filename = arg
+ if not isinstance(filename, str):
+ filename = str(filename, sys.getfilesystemencoding())
+ if filename.endswith(('.osz', '.oszl')):
+ self.service_manager_contents.load_file(filename)
diff --git a/openlp/core/ui/media/__init__.py b/openlp/core/ui/media/__init__.py
index 1276c8662..8cc10b6a1 100644
--- a/openlp/core/ui/media/__init__.py
+++ b/openlp/core/ui/media/__init__.py
@@ -35,7 +35,7 @@ from openlp.core.common import Settings
from PyQt4 import QtCore
-log = logging.getLogger(__name__+'.__init__')
+log = logging.getLogger(__name__ + '.__init__')
class MediaState(object):
diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py
index d846af0e4..596b618cb 100644
--- a/openlp/core/ui/media/mediacontroller.py
+++ b/openlp/core/ui/media/mediacontroller.py
@@ -137,7 +137,7 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
for player in list(self.media_players.values()):
if player.is_active:
for item in player.audio_extensions_list:
- if not item in self.audio_extensions_list:
+ if item not in self.audio_extensions_list:
self.audio_extensions_list.append(item)
suffix_list.append(item[2:])
self.video_extensions_list = []
@@ -184,8 +184,8 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
return False
saved_players, overridden_player = get_media_players()
invalid_media_players = \
- [mediaPlayer for mediaPlayer in saved_players if not mediaPlayer in self.media_players or
- not self.media_players[mediaPlayer].check_available()]
+ [media_player for media_player in saved_players if media_player not in self.media_players or
+ not self.media_players[media_player].check_available()]
if invalid_media_players:
for invalidPlayer in invalid_media_players:
saved_players.remove(invalidPlayer)
@@ -506,7 +506,8 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
else:
self.media_volume(controller, controller.media_info.volume)
if status:
- display.frame.evaluateJavaScript('show_blank("desktop");')
+ if not controller.media_info.is_background:
+ display.frame.evaluateJavaScript('show_blank("desktop");')
self.current_media_players[controller.controller_type].set_visible(display, True)
# Flash needs to be played and will not AutoPlay
if controller.media_info.is_flash:
@@ -517,7 +518,7 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
controller.mediabar.actions['playbackPause'].setVisible(True)
controller.mediabar.actions['playbackStop'].setVisible(True)
if controller.is_live:
- if controller.hide_menu.defaultAction().isChecked():
+ if controller.hide_menu.defaultAction().isChecked() and not controller.media_info.is_background:
controller.hide_menu.defaultAction().trigger()
# Start Timer for ui updates
if not self.timer.isActive():
diff --git a/openlp/core/ui/media/vendor/vlc.py b/openlp/core/ui/media/vendor/vlc.py
index 6e17c002f..0326e4104 100644
--- a/openlp/core/ui/media/vendor/vlc.py
+++ b/openlp/core/ui/media/vendor/vlc.py
@@ -48,13 +48,13 @@ import sys
from inspect import getargspec
__version__ = "N/A"
-build_date = "Mon Apr 1 23:47:38 2013"
+build_date = "Tue Jul 2 10:35:53 2013"
if sys.version_info[0] > 2:
str = str
- str = str
+ unicode = str
bytes = bytes
- str = (str, bytes)
+ basestring = (str, bytes)
PYTHON3 = True
def str_to_bytes(s):
"""Translate string or bytes to bytes.
@@ -73,14 +73,14 @@ if sys.version_info[0] > 2:
return b
else:
str = str
- str = str
+ unicode = unicode
bytes = str
- str = str
+ basestring = basestring
PYTHON3 = False
def str_to_bytes(s):
"""Translate string or bytes to bytes.
"""
- if isinstance(s, str):
+ if isinstance(s, unicode):
return s.encode(sys.getfilesystemencoding())
else:
return s
@@ -89,7 +89,7 @@ else:
"""Translate bytes to unicode string.
"""
if isinstance(b, str):
- return str(b, sys.getfilesystemencoding())
+ return unicode(b, sys.getfilesystemencoding())
else:
return b
@@ -110,7 +110,7 @@ def find_lib():
p = find_library('libvlc.dll')
if p is None:
try: # some registry settings
- import winreg as w # leaner than win32api, win32con
+ import _winreg as w # leaner than win32api, win32con
for r in w.HKEY_LOCAL_MACHINE, w.HKEY_CURRENT_USER:
try:
r = w.OpenKey(r, 'Software\\VideoLAN\\VLC')
@@ -168,7 +168,7 @@ class VLCException(Exception):
pass
try:
- _Ints = (int, int)
+ _Ints = (int, long)
except NameError: # no long in Python 3+
_Ints = int
_Seqs = (list, tuple)
@@ -327,6 +327,9 @@ class _Enum(ctypes.c_uint):
n = self._enum_names_.get(self.value, '') or ('FIXME_(%r)' % (self.value,))
return '.'.join((self.__class__.__name__, n))
+ def __hash__(self):
+ return self.value
+
def __repr__(self):
return '.'.join((self.__class__.__module__, self.__str__()))
@@ -1294,7 +1297,7 @@ class Instance(_Ctype):
i = args[0]
if isinstance(i, _Ints):
return _Constructor(cls, i)
- elif isinstance(i, str):
+ elif isinstance(i, basestring):
args = i.strip().split()
elif isinstance(i, _Seqs):
args = i
@@ -2078,7 +2081,7 @@ class MediaList(_Ctype):
@param mrl: a media instance or a MRL.
@return: 0 on success, -1 if the media list is read-only.
"""
- if isinstance(mrl, str):
+ if isinstance(mrl, basestring):
mrl = (self.get_instance() or get_default_instance()).media_new(mrl)
return libvlc_media_list_add_media(self, mrl)
@@ -3351,6 +3354,39 @@ def libvlc_event_type_name(event_type):
ctypes.c_char_p, ctypes.c_uint)
return f(event_type)
+def libvlc_log_get_context(ctx):
+ '''Gets debugging informations about a log message: the name of the VLC module
+ emitting the message and the message location within the source code.
+ The returned module name and file name will be NULL if unknown.
+ The returned line number will similarly be zero if unknown.
+ @param ctx: message context (as passed to the @ref libvlc_log_cb callback).
+ @return: module module name storage (or NULL), file source code file name storage (or NULL), line source code file line number storage (or NULL).
+ @version: LibVLC 2.1.0 or later.
+ '''
+ f = _Cfunctions.get('libvlc_log_get_context', None) or \
+ _Cfunction('libvlc_log_get_context', ((1,), (2,), (2,), (2,),), None,
+ None, Log_ptr, ListPOINTER(ctypes.c_char_p), ListPOINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_uint))
+ return f(ctx)
+
+def libvlc_log_get_object(ctx, id):
+ '''Gets VLC object informations about a log message: the type name of the VLC
+ object emitting the message, the object header if any and a temporaly-unique
+ object identifier. These informations are mainly meant for B{manual}
+ troubleshooting.
+ The returned type name may be "generic" if unknown, but it cannot be NULL.
+ The returned header will be NULL if unset; in current versions, the header
+ is used to distinguish for VLM inputs.
+ The returned object ID will be zero if the message is not associated with
+ any VLC object.
+ @param ctx: message context (as passed to the @ref libvlc_log_cb callback).
+ @return: name object name storage (or NULL), header object header (or NULL), line source code file line number storage (or NULL).
+ @version: LibVLC 2.1.0 or later.
+ '''
+ f = _Cfunctions.get('libvlc_log_get_object', None) or \
+ _Cfunction('libvlc_log_get_object', ((1,), (2,), (2,), (1,),), None,
+ None, Log_ptr, ListPOINTER(ctypes.c_char_p), ListPOINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_uint))
+ return f(ctx, id)
+
def libvlc_log_unset(p_instance):
'''Unsets the logging callback for a LibVLC instance. This is rarely needed:
the callback is implicitly unset when the instance is destroyed.
@@ -5827,7 +5863,7 @@ def libvlc_vlm_get_event_manager(p_instance):
# libvlc_printerr
# libvlc_set_exit_handler
-# 15 function(s) not wrapped as methods:
+# 17 function(s) not wrapped as methods:
# libvlc_audio_output_device_list_release
# libvlc_audio_output_list_release
# libvlc_clearerr
@@ -5838,6 +5874,8 @@ def libvlc_vlm_get_event_manager(p_instance):
# libvlc_get_changeset
# libvlc_get_compiler
# libvlc_get_version
+# libvlc_log_get_context
+# libvlc_log_get_object
# libvlc_media_tracks_release
# libvlc_module_description_list_release
# libvlc_new
@@ -5910,9 +5948,9 @@ def debug_callback(event, *args, **kwds):
'''
l = ['event %s' % (event.type,)]
if args:
- l.extend(list(map(str, args)))
+ l.extend(map(str, args))
if kwds:
- l.extend(sorted('%s=%s' % t for t in list(kwds.items())))
+ l.extend(sorted('%s=%s' % t for t in kwds.items()))
print('Debug callback (%s)' % ', '.join(l))
if __name__ == '__main__':
diff --git a/openlp/core/ui/media/webkitplayer.py b/openlp/core/ui/media/webkitplayer.py
index e3a522140..38e691494 100644
--- a/openlp/core/ui/media/webkitplayer.py
+++ b/openlp/core/ui/media/webkitplayer.py
@@ -174,34 +174,11 @@ FLASH_HTML = """
"""
-VIDEO_EXT = [
- '*.3gp',
- '*.3gpp',
- '*.3g2',
- '*.3gpp2',
- '*.aac',
- '*.flv',
- '*.f4a',
- '*.f4b',
- '*.f4p',
- '*.f4v',
- '*.mov',
- '*.m4a',
- '*.m4b',
- '*.m4p',
- '*.m4v',
- '*.mkv',
- '*.mp4',
- '*.ogv',
- '*.webm',
- '*.mpg', '*.wmv', '*.mpeg', '*.avi',
- '*.swf'
-]
+VIDEO_EXT = ['*.3gp', '*.3gpp', '*.3g2', '*.3gpp2', '*.aac', '*.flv', '*.f4a', '*.f4b', '*.f4p', '*.f4v', '*.mov',
+ '*.m4a', '*.m4b', '*.m4p', '*.m4v', '*.mkv', '*.mp4', '*.ogv', '*.webm', '*.mpg', '*.wmv', '*.mpeg',
+ '*.avi', '*.swf']
-AUDIO_EXT = [
- '*.mp3',
- '*.ogg'
-]
+AUDIO_EXT = ['*.mp3', '*.ogg']
class WebkitPlayer(MediaPlayer):
@@ -411,10 +388,9 @@ class WebkitPlayer(MediaPlayer):
"""
Return some information about this player
"""
- return(translate('Media.player', 'Webkit is a media player which runs '
- 'inside a web browser. This player allows text over video to be '
- 'rendered.') +
- '
' + translate('Media.player', 'Audio') +
- '
' + str(AUDIO_EXT) + '
' +
- translate('Media.player', 'Video') + '
' +
- str(VIDEO_EXT) + '
')
+ part1 = translate('Media.player', 'Webkit is a media player which runs inside a web browser. This player '
+ 'allows text over video to be rendered.')
+ part2 = translate('Media.player', 'Audio')
+ part3 = translate('Media.player', 'Video')
+ return part1 + '
' + part2 + '
' + str(AUDIO_EXT) + '
' + part3 + \
+ '
' + str(VIDEO_EXT) + '
'
diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py
index c2b36551a..70cbd6141 100644
--- a/openlp/core/ui/servicemanager.py
+++ b/openlp/core/ui/servicemanager.py
@@ -234,6 +234,9 @@ class Ui_ServiceManager(object):
self.menu = QtGui.QMenu()
self.edit_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', '&Edit Item'),
icon=':/general/general_edit.png', triggers=self.remote_edit)
+ self.rename_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', '&Rename...'),
+ icon=':/general/general_edit.png',
+ triggers=self.on_service_item_rename)
self.maintain_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', '&Reorder Item'),
icon=':/general/general_edit.png',
triggers=self.on_service_item_edit_form)
@@ -399,7 +402,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
:param suffix_list: New Suffix's to be supported
"""
for suffix in suffix_list:
- if not suffix in self.suffixes:
+ if suffix not in self.suffixes:
self.suffixes.append(suffix)
def on_new_service_clicked(self, field=None):
@@ -629,7 +632,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
for item in self.service_items:
self.main_window.increment_progress_bar()
service_item = item['service_item'].get_service_repr(self._save_lite)
- #TODO: check for file item on save.
+ # TODO: check for file item on save.
service.append({'serviceitem': service_item})
self.main_window.increment_progress_bar()
service_content = json.dumps(service)
@@ -754,8 +757,9 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
items = json.load(file_to)
else:
critical_error_message_box(message=translate('OpenLP.ServiceManager',
- 'The service file you are trying to open is in an old format.\n '
- 'Please save it using OpenLP 2.0.2 or greater.'))
+ 'The service file you are trying to open is in an old '
+ 'format.\n Please save it using OpenLP 2.0.2 or '
+ 'greater.'))
return
file_to.close()
self.new_file()
@@ -848,6 +852,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
pos = item.data(0, QtCore.Qt.UserRole)
service_item = self.service_items[pos - 1]
self.edit_action.setVisible(False)
+ self.rename_action.setVisible(False)
self.create_custom_action.setVisible(False)
self.maintain_action.setVisible(False)
self.notes_action.setVisible(False)
@@ -855,6 +860,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
self.auto_start_action.setVisible(False)
if service_item['service_item'].is_capable(ItemCapabilities.CanEdit) and service_item['service_item'].edit_id:
self.edit_action.setVisible(True)
+ if service_item['service_item'].is_capable(ItemCapabilities.CanEditTitle):
+ self.rename_action.setVisible(True)
if service_item['service_item'].is_capable(ItemCapabilities.CanMaintain):
self.maintain_action.setVisible(True)
if item.parent() is None:
@@ -1482,6 +1489,24 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
if new_item:
self.add_service_item(new_item, replace=True)
+ def on_service_item_rename(self, field=None):
+ """
+ Opens a dialog to rename the service item.
+
+ :param field: Not used, but PyQt needs this.
+ """
+ item = self.find_service_item()[0]
+ if not self.service_items[item]['service_item'].is_capable(ItemCapabilities.CanEditTitle):
+ return
+ title = self.service_items[item]['service_item'].title
+ title, ok = QtGui.QInputDialog.getText(self, translate('OpenLP.ServiceManager', 'Rename item title'),
+ translate('OpenLP.ServiceManager', 'Title:'),
+ QtGui.QLineEdit.Normal, self.trUtf8(title))
+ if ok:
+ self.service_items[item]['service_item'].title = title
+ self.repaint_service_list(item, -1)
+ self.set_modified()
+
def create_custom(self, field=None):
"""
Saves the current text item as a custom slide
diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py
index 5aba66ef2..a1077e1f4 100644
--- a/openlp/core/ui/settingsform.py
+++ b/openlp/core/ui/settingsform.py
@@ -150,5 +150,5 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog, RegistryProperties):
:param function: The function to be called
"""
- if not function in self.processes:
+ if function not in self.processes:
self.processes.append(function)
diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py
index 7faf10ca2..bf92e9d76 100644
--- a/openlp/core/ui/slidecontroller.py
+++ b/openlp/core/ui/slidecontroller.py
@@ -495,14 +495,14 @@ class SlideController(DisplayController, RegistryProperties):
self.on_theme_display(False)
self.on_hide_display(False)
- def service_previous(self):
+ def service_previous(self, field=None):
"""
Live event to select the previous service item from the service manager.
"""
self.keypress_queue.append(ServiceItemAction.Previous)
self._process_queue()
- def service_next(self):
+ def service_next(self, field=None):
"""
Live event to select the next service item from the service manager.
"""
@@ -1039,7 +1039,6 @@ class SlideController(DisplayController, RegistryProperties):
"""
self.preview_widget.change_slide(row)
self.update_preview()
- Registry().execute('slidecontroller_%s_changed' % self.type_prefix, row)
def update_preview(self):
"""
diff --git a/openlp/core/ui/themelayoutdialog.py b/openlp/core/ui/themelayoutdialog.py
index bf6c1069a..023d6259c 100644
--- a/openlp/core/ui/themelayoutdialog.py
+++ b/openlp/core/ui/themelayoutdialog.py
@@ -44,7 +44,6 @@ class Ui_ThemeLayoutDialog(object):
Set up the UI
"""
themeLayoutDialog.setObjectName('themeLayoutDialogDialog')
- #themeLayoutDialog.resize(300, 200)
self.preview_layout = QtGui.QVBoxLayout(themeLayoutDialog)
self.preview_layout.setObjectName('preview_layout')
self.preview_area = QtGui.QWidget(themeLayoutDialog)
diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py
index 32ed30303..1f54f984b 100644
--- a/openlp/core/ui/themestab.py
+++ b/openlp/core/ui/themestab.py
@@ -114,17 +114,19 @@ class ThemesTab(SettingsTab):
self.global_group_box.setTitle(translate('OpenLP.ThemesTab', 'Global Theme'))
self.level_group_box.setTitle(translate('OpenLP.ThemesTab', 'Theme Level'))
self.song_level_radio_button.setText(translate('OpenLP.ThemesTab', 'S&ong Level'))
- self.song_level_label.setText(translate('OpenLP.ThemesTab', 'Use the theme from each song '
- 'in the database. If a song doesn\'t have a theme associated with '
- 'it, then use the service\'s theme. If the service doesn\'t have '
- 'a theme, then use the global theme.'))
+ self.song_level_label.setText(
+ translate('OpenLP.ThemesTab', 'Use the theme from each song in the database. If a song doesn\'t have a '
+ 'theme associated with it, then use the service\'s theme. If the service '
+ 'doesn\'t have a theme, then use the global theme.'))
self.service_level_radio_button.setText(translate('OpenLP.ThemesTab', '&Service Level'))
- self.service_level_label.setText(translate('OpenLP.ThemesTab', 'Use the theme from the service, '
- 'overriding any of the individual songs\' themes. If the '
- 'service doesn\'t have a theme, then use the global theme.'))
+ self.service_level_label.setText(
+ translate('OpenLP.ThemesTab', 'Use the theme from the service, overriding any of the individual '
+ 'songs\' themes. If the service doesn\'t have a theme, then use the global '
+ 'theme.'))
self.global_level_radio_button.setText(translate('OpenLP.ThemesTab', '&Global Level'))
- self.global_level_label.setText(translate('OpenLP.ThemesTab', 'Use the global theme, overriding '
- 'any themes associated with either the service or the songs.'))
+ self.global_level_label.setText(translate('OpenLP.ThemesTab', 'Use the global theme, overriding any themes '
+ 'associated with either the service or the '
+ 'songs.'))
def load(self):
"""
diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py
index 746c50d71..a5b5f356a 100644
--- a/openlp/core/utils/__init__.py
+++ b/openlp/core/utils/__init__.py
@@ -56,7 +56,7 @@ if sys.platform != 'win32' and sys.platform != 'darwin':
from openlp.core.common import translate
-log = logging.getLogger(__name__+'.__init__')
+log = logging.getLogger(__name__ + '.__init__')
APPLICATION_VERSION = {}
IMAGES_FILTER = None
diff --git a/openlp/core/utils/languagemanager.py b/openlp/core/utils/languagemanager.py
index cd5ce7add..bb584f7bd 100644
--- a/openlp/core/utils/languagemanager.py
+++ b/openlp/core/utils/languagemanager.py
@@ -74,7 +74,7 @@ class LanguageManager(object):
log.debug('Translation files: %s', AppLocation.get_directory(
AppLocation.LanguageDir))
trans_dir = QtCore.QDir(AppLocation.get_directory(AppLocation.LanguageDir))
- file_names = trans_dir.entryList('*.qm', QtCore.QDir.Files, QtCore.QDir.Name)
+ file_names = trans_dir.entryList(['*.qm'], QtCore.QDir.Files, QtCore.QDir.Name)
# Remove qm files from the list which start with "qt_".
file_names = [file_ for file_ in file_names if not file_.startswith('qt_')]
return list(map(trans_dir.filePath, file_names))
diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py
index cf3b7d0ce..76efadf32 100644
--- a/openlp/plugins/alerts/alertsplugin.py
+++ b/openlp/plugins/alerts/alertsplugin.py
@@ -207,12 +207,12 @@ class AlertsPlugin(Plugin):
"""
Called to define all translatable texts of the plugin
"""
- ## Name PluginList ##
+ # Name PluginList
self.text_strings[StringContent.Name] = {
'singular': translate('AlertsPlugin', 'Alert', 'name singular'),
'plural': translate('AlertsPlugin', 'Alerts', 'name plural')
}
- ## Name for MediaDockManager, SettingsManager ##
+ # Name for MediaDockManager, SettingsManager
self.text_strings[StringContent.VisibleName] = {
'title': translate('AlertsPlugin', 'Alerts', 'container title')
}
diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py
index 5a51be163..e7f1fdd56 100644
--- a/openlp/plugins/bibles/bibleplugin.py
+++ b/openlp/plugins/bibles/bibleplugin.py
@@ -88,8 +88,6 @@ class BiblePlugin(Plugin):
self.import_bible_item.setVisible(True)
action_list = ActionList.get_instance()
action_list.add_action(self.import_bible_item, UiStrings().Import)
- # Do not add the action to the list yet.
- #action_list.add_action(self.export_bible_item, UiStrings().Export)
# Set to invisible until we can export bibles
self.export_bible_item.setVisible(False)
self.tools_upgrade_item.setVisible(bool(self.manager.old_bible_databases))
@@ -104,7 +102,6 @@ class BiblePlugin(Plugin):
action_list = ActionList.get_instance()
action_list.remove_action(self.import_bible_item, UiStrings().Import)
self.import_bible_item.setVisible(False)
- #action_list.remove_action(self.export_bible_item, UiStrings().Export)
self.export_bible_item.setVisible(False)
def app_startup(self):
@@ -115,19 +112,27 @@ class BiblePlugin(Plugin):
if self.manager.old_bible_databases:
if QtGui.QMessageBox.information(
self.main_window, translate('OpenLP', 'Information'),
- translate('OpenLP', 'Bible format has changed.\nYou have to upgrade your existing Bibles.\n'
- 'Should OpenLP upgrade now?'),
- QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)) == \
+ translate('OpenLP', 'Bible format has changed.\nYou have to upgrade your '
+ 'existing Bibles.\nShould OpenLP upgrade now?'),
+ QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)) == \
QtGui.QMessageBox.Yes:
self.on_tools_upgrade_Item_triggered()
def add_import_menu_item(self, import_menu):
+ """
+
+ :param import_menu:
+ """
self.import_bible_item = create_action(import_menu, 'importBibleItem',
text=translate('BiblesPlugin', '&Bible'), visible=False,
triggers=self.on_bible_import_click)
import_menu.addAction(self.import_bible_item)
- def add_export_menu_Item(self, export_menu):
+ def add_export_menu_item(self, export_menu):
+ """
+
+ :param export_menu:
+ """
self.export_bible_item = create_action(export_menu, 'exportBibleItem',
text=translate('BiblesPlugin', '&Bible'), visible=False)
export_menu.addAction(self.export_bible_item)
@@ -190,12 +195,12 @@ class BiblePlugin(Plugin):
"""
Called to define all translatable texts of the plugin
"""
- ## Name PluginList ##
+ # Name PluginList
self.text_strings[StringContent.Name] = {
'singular': translate('BiblesPlugin', 'Bible', 'name singular'),
'plural': translate('BiblesPlugin', 'Bibles', 'name plural')
}
- ## Name for MediaDockManager, SettingsManager ##
+ # Name for MediaDockManager, SettingsManager
self.text_strings[StringContent.VisibleName] = {
'title': translate('BiblesPlugin', 'Bibles', 'container title')
}
diff --git a/openlp/plugins/bibles/forms/bibleupgradeform.py b/openlp/plugins/bibles/forms/bibleupgradeform.py
index 9925b1ebc..d9936dfe6 100644
--- a/openlp/plugins/bibles/forms/bibleupgradeform.py
+++ b/openlp/plugins/bibles/forms/bibleupgradeform.py
@@ -78,7 +78,7 @@ class BibleUpgradeForm(OpenLPWizard):
Set up the UI for the bible wizard.
"""
super(BibleUpgradeForm, self).setupUi(image)
- Registry().execute('openlp_stop_wizard', self.stop_import)
+ Registry().register_function('openlp_stop_wizard', self.stop_import)
def stop_import(self):
"""
diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py
index 9ffa5d53e..203d86406 100644
--- a/openlp/plugins/bibles/lib/db.py
+++ b/openlp/plugins/bibles/lib/db.py
@@ -32,9 +32,11 @@ import logging
import os
import re
import sqlite3
+import time
from PyQt4 import QtCore
from sqlalchemy import Column, ForeignKey, Table, or_, types, func
+from sqlalchemy.exc import OperationalError
from sqlalchemy.orm import class_mapper, mapper, relation
from sqlalchemy.orm.exc import UnmappedClassError
@@ -154,7 +156,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
if 'path' in kwargs:
self.path = kwargs['path']
self.wizard = None
- Registry().execute('openlp_stop_wizard', self.stop_import)
+ Registry().register_function('openlp_stop_wizard', self.stop_import)
def stop_import(self):
"""
@@ -191,7 +193,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
:param testament: *Defaults to 1.* The testament_reference_id from
bibles_resources.sqlite of the testament this book belongs to.
"""
- log.debug('BibleDB.create_book("%s", "%s")', name, bk_ref_id)
+ log.debug('BibleDB.create_book("%s", "%s")' % (name, bk_ref_id))
book = Book.populate(name=name, book_reference_id=bk_ref_id, testament_reference_id=testament)
self.save_object(book)
return book
@@ -202,7 +204,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
:param book: The book object
"""
- log.debug('BibleDB.update_book("%s")', book.name)
+ log.debug('BibleDB.update_book("%s")' % book.name)
return self.save_object(book)
def delete_book(self, db_book):
@@ -211,7 +213,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
:param db_book: The book object.
"""
- log.debug('BibleDB.delete_book("%s")', db_book.name)
+ log.debug('BibleDB.delete_book("%s")' % db_book.name)
if self.delete_object(Book, db_book.id):
return True
return False
@@ -225,7 +227,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
:param text_list: A dict of the verses to be inserted. The key is the verse number, and the value is the
verse text.
"""
- log.debug('BibleDBcreate_chapter("%s", "%s")', book_id, chapter)
+ log.debug('BibleDBcreate_chapter("%s", "%s")' % (book_id, chapter))
# Text list has book and chapter as first two elements of the array.
for verse_number, verse_text in text_list.items():
verse = Verse.populate(
@@ -235,7 +237,12 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
text=verse_text
)
self.session.add(verse)
- self.session.commit()
+ try:
+ self.session.commit()
+ except OperationalError:
+ # Wait 10ms and try again (lp#1154467)
+ time.sleep(0.01)
+ self.session.commit()
def create_verse(self, book_id, chapter, verse, text):
"""
@@ -267,7 +274,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
"""
if not isinstance(value, str):
value = str(value)
- log.debug('BibleDB.save_meta("%s/%s")', key, value)
+ log.debug('BibleDB.save_meta("%s/%s")' % (key, value))
meta = self.get_object(BibleMeta, key)
if meta:
meta.value = value
@@ -281,7 +288,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
:param book: The name of the book to return.
"""
- log.debug('BibleDB.get_book("%s")', book)
+ log.debug('BibleDB.get_book("%s")' % book)
return self.get_object_filtered(Book, Book.name.like(book + '%'))
def get_books(self):
@@ -292,17 +299,17 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
log.debug('BibleDB.get_books()')
return self.get_all_objects(Book, order_by_ref=Book.id)
- def get_book_by_book_ref_id(self, id):
+ def get_book_by_book_ref_id(self, ref_id):
"""
Return a book object from the database.
- :param id: The reference id of the book to return.
+ :param ref_id: The reference id of the book to return.
"""
- log.debug('BibleDB.get_book_by_book_ref_id("%s")', id)
- return self.get_object_filtered(Book, Book.book_reference_id.like(id))
+ log.debug('BibleDB.get_book_by_book_ref_id("%s")' % ref_id)
+ return self.get_object_filtered(Book, Book.book_reference_id.like(ref_id))
def get_book_ref_id_by_name(self, book, maxbooks, language_id=None):
- log.debug('BibleDB.get_book_ref_id_by_name:("%s", "%s")', book, language_id)
+ log.debug('BibleDB.get_book_ref_id_by_name:("%s", "%s")' % (book, language_id))
book_id = None
if BiblesResourcesDB.get_book(book, True):
book_temp = BiblesResourcesDB.get_book(book, True)
@@ -328,7 +335,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
:param book: The name of the book, according to the selected language.
:param language_selection: The language selection the user has chosen in the settings section of the Bible.
"""
- log.debug('get_book_ref_id_by_localised_name("%s", "%s")', book, language_selection)
+ log.debug('get_book_ref_id_by_localised_name("%s", "%s")' % (book, language_selection))
from openlp.plugins.bibles.lib import LanguageSelection, BibleStrings
book_names = BibleStrings().BookNames
# escape reserved characters
@@ -376,14 +383,14 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
[(u'35', 1, 1, 1), (u'35', 2, 2, 3)]
:param show_error:
"""
- log.debug('BibleDB.get_verses("%s")', reference_list)
+ log.debug('BibleDB.get_verses("%s")' % reference_list)
verse_list = []
book_error = False
for book_id, chapter, start_verse, end_verse in reference_list:
db_book = self.get_book_by_book_ref_id(book_id)
if db_book:
book_id = db_book.book_reference_id
- log.debug('Book name corrected to "%s"', db_book.name)
+ log.debug('Book name corrected to "%s"' % db_book.name)
if end_verse == -1:
end_verse = self.get_verse_count(book_id, chapter)
verses = self.session.query(Verse) \
@@ -395,7 +402,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
.all()
verse_list.extend(verses)
else:
- log.debug('OpenLP failed to find book with id "%s"', book_id)
+ log.debug('OpenLP failed to find book with id "%s"' % book_id)
book_error = True
if book_error and show_error:
critical_error_message_box(
@@ -414,7 +421,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
contains spaces, it will split apart and AND'd on the list of
values.
"""
- log.debug('BibleDB.verse_search("%s")', text)
+ log.debug('BibleDB.verse_search("%s")' % text)
verses = self.session.query(Verse)
if text.find(',') > -1:
keywords = ['%%%s%%' % keyword.strip() for keyword in text.split(',')]
@@ -433,7 +440,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
:param book: The book object to get the chapter count for.
"""
- log.debug('BibleDB.get_chapter_count("%s")', book.name)
+ log.debug('BibleDB.get_chapter_count("%s")' % book.name)
count = self.session.query(func.max(Verse.chapter)).join(Book).filter(
Book.book_reference_id == book.book_reference_id).scalar()
if not count:
@@ -447,7 +454,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
:param book_ref_id: The book reference id.
:param chapter: The chapter to get the verse count for.
"""
- log.debug('BibleDB.get_verse_count("%s", "%s")', book_ref_id, chapter)
+ log.debug('BibleDB.get_verse_count("%s", "%s")' % (book_ref_id, chapter))
count = self.session.query(func.max(Verse.verse)).join(Book) \
.filter(Book.book_reference_id == book_ref_id) \
.filter(Verse.chapter == chapter) \
@@ -563,7 +570,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
:param name: The name or abbreviation of the book.
:param lower: True if the comparison should be only lowercase
"""
- log.debug('BiblesResourcesDB.get_book("%s")', name)
+ log.debug('BiblesResourcesDB.get_book("%s")' % name)
if not isinstance(name, str):
name = str(name)
if lower:
@@ -592,7 +599,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
:param string: The string to search for in the book names or abbreviations.
"""
- log.debug('BiblesResourcesDB.get_book_like("%s")', string)
+ log.debug('BiblesResourcesDB.get_book_like("%s")' % string)
if not isinstance(string, str):
name = str(string)
books = BiblesResourcesDB.run_sql(
@@ -611,17 +618,17 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
return None
@staticmethod
- def get_book_by_id(id):
+ def get_book_by_id(book_id):
"""
Return a book by id.
- :param id: The id of the book.
+ :param book_id: The id of the book.
"""
- log.debug('BiblesResourcesDB.get_book_by_id("%s")', id)
- if not isinstance(id, int):
- id = int(id)
+ log.debug('BiblesResourcesDB.get_book_by_id("%s")' % book_id)
+ if not isinstance(book_id, int):
+ book_id = int(book_id)
books = BiblesResourcesDB.run_sql(
- 'SELECT id, testament_id, name, abbreviation, chapters FROM book_reference WHERE id = ?', (id, ))
+ 'SELECT id, testament_id, name, abbreviation, chapters FROM book_reference WHERE id = ?', (book_id, ))
if books:
return {
'id': books[0][0],
@@ -641,7 +648,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
:param book_ref_id: The id of a book.
:param chapter: The chapter number.
"""
- log.debug('BiblesResourcesDB.get_chapter("%s", "%s")', book_ref_id, chapter)
+ log.debug('BiblesResourcesDB.get_chapter("%s", "%s")' % (book_ref_id, chapter))
if not isinstance(chapter, int):
chapter = int(chapter)
chapters = BiblesResourcesDB.run_sql(
@@ -649,10 +656,10 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
'chapter, verse_count FROM chapters WHERE book_reference_id = ?', (book_ref_id,))
try:
return {
- 'id': chapters[chapter-1][0],
- 'book_reference_id': chapters[chapter-1][1],
- 'chapter': chapters[chapter-1][2],
- 'verse_count': chapters[chapter-1][3]
+ 'id': chapters[chapter - 1][0],
+ 'book_reference_id': chapters[chapter - 1][1],
+ 'chapter': chapters[chapter - 1][2],
+ 'verse_count': chapters[chapter - 1][3]
}
except (IndexError, TypeError):
return None
@@ -664,7 +671,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
:param book_ref_id: The id of the book.
"""
- log.debug('BiblesResourcesDB.get_chapter_count("%s")', book_ref_id)
+ log.debug('BiblesResourcesDB.get_chapter_count("%s")' % book_ref_id)
details = BiblesResourcesDB.get_book_by_id(book_ref_id)
if details:
return details['chapters']
@@ -678,7 +685,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
:param book_ref_id: The id of the book.
:param chapter: The number of the chapter.
"""
- log.debug('BiblesResourcesDB.get_verse_count("%s", "%s")', book_ref_id, chapter)
+ log.debug('BiblesResourcesDB.get_verse_count("%s", "%s")' % (book_ref_id, chapter))
details = BiblesResourcesDB.get_chapter(book_ref_id, chapter)
if details:
return details['verse_count']
@@ -691,7 +698,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
:param source: The name or abbreviation of the book.
"""
- log.debug('BiblesResourcesDB.get_download_source("%s")', source)
+ log.debug('BiblesResourcesDB.get_download_source("%s")' % source)
if not isinstance(source, str):
source = str(source)
source = source.title()
@@ -712,7 +719,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
:param source: The source of the web_bible.
"""
- log.debug('BiblesResourcesDB.get_webbibles("%s")', source)
+ log.debug('BiblesResourcesDB.get_webbibles("%s")' % source)
if not isinstance(source, str):
source = str(source)
source = BiblesResourcesDB.get_download_source(source)
@@ -737,7 +744,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
:param abbreviation: The abbreviation of the web_bible.
:param source: The source of the web_bible.
"""
- log.debug('BiblesResourcesDB.get_webbibles("%s", "%s")', abbreviation, source)
+ log.debug('BiblesResourcesDB.get_webbibles("%s", "%s")' % (abbreviation, source))
if not isinstance(abbreviation, str):
abbreviation = str(abbreviation)
if not isinstance(source, str):
@@ -765,7 +772,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
:param name: The name to search the id.
:param language_id: The language_id for which language should be searched
"""
- log.debug('BiblesResourcesDB.get_alternative_book_name("%s", "%s")', name, language_id)
+ log.debug('BiblesResourcesDB.get_alternative_book_name("%s", "%s")' % (name, language_id))
if language_id:
books = BiblesResourcesDB.run_sql(
'SELECT book_reference_id, name FROM alternative_book_names WHERE language_id = ? ORDER BY id',
@@ -784,7 +791,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
:param name: The name or abbreviation of the language.
"""
- log.debug('BiblesResourcesDB.get_language("%s")', name)
+ log.debug('BiblesResourcesDB.get_language("%s")' % name)
if not isinstance(name, str):
name = str(name)
language = BiblesResourcesDB.run_sql(
@@ -846,13 +853,13 @@ class AlternativeBookNamesDB(QtCore.QObject, Manager):
file_path = os.path.join(
AppLocation.get_directory(AppLocation.DataDir), 'bibles', 'alternative_book_names.sqlite')
if not os.path.exists(file_path):
- #create new DB, create table alternative_book_names
+ # create new DB, create table alternative_book_names
AlternativeBookNamesDB.conn = sqlite3.connect(file_path)
AlternativeBookNamesDB.conn.execute(
'CREATE TABLE alternative_book_names(id INTEGER NOT NULL, '
'book_reference_id INTEGER, language_id INTEGER, name VARCHAR(50), PRIMARY KEY (id))')
else:
- #use existing DB
+ # use existing DB
AlternativeBookNamesDB.conn = sqlite3.connect(file_path)
AlternativeBookNamesDB.cursor = AlternativeBookNamesDB.conn.cursor()
return AlternativeBookNamesDB.cursor
@@ -880,7 +887,7 @@ class AlternativeBookNamesDB(QtCore.QObject, Manager):
:param name: The name to search the id.
:param language_id: The language_id for which language should be searched
"""
- log.debug('AlternativeBookNamesDB.get_book_reference_id("%s", "%s")', name, language_id)
+ log.debug('AlternativeBookNamesDB.get_book_reference_id("%s", "%s")' % (name, language_id))
if language_id:
books = AlternativeBookNamesDB.run_sql(
'SELECT book_reference_id, name FROM alternative_book_names WHERE language_id = ?', (language_id, ))
@@ -901,8 +908,8 @@ class AlternativeBookNamesDB(QtCore.QObject, Manager):
:param book_reference_id: The book_reference_id of the book.
:param language_id: The language to which the alternative book name belong.
"""
- log.debug('AlternativeBookNamesDB.create_alternative_book_name("%s", "%s", "%s")',
- name, book_reference_id, language_id)
+ log.debug('AlternativeBookNamesDB.create_alternative_book_name("%s", "%s", "%s")' %
+ (name, book_reference_id, language_id))
return AlternativeBookNamesDB.run_sql(
'INSERT INTO alternative_book_names(book_reference_id, language_id, name) '
'VALUES (?, ?, ?)', (book_reference_id, language_id, name), True)
diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py
index 340d8ef92..b15e11738 100644
--- a/openlp/plugins/bibles/lib/http.py
+++ b/openlp/plugins/bibles/lib/http.py
@@ -552,10 +552,10 @@ class HTTPBible(BibleDB, RegistryProperties):
self.application.set_busy_cursor()
search_results = self.get_chapter(book, reference[1])
if search_results and search_results.has_verse_list():
- ## We have found a book of the bible lets check to see
- ## if it was there. By reusing the returned book name
- ## we get a correct book. For example it is possible
- ## to request ac and get Acts back.
+ # We have found a book of the bible lets check to see
+ # if it was there. By reusing the returned book name
+ # we get a correct book. For example it is possible
+ # to request ac and get Acts back.
book_name = search_results.book
self.application.process_events()
# Check to see if book/chapter exists.
diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py
index 10fef8e31..a2cb1b594 100644
--- a/openlp/plugins/bibles/lib/mediaitem.py
+++ b/openlp/plugins/bibles/lib/mediaitem.py
@@ -480,6 +480,10 @@ class BibleMediaItem(MediaManagerItem):
self.reload_bibles()
def on_delete_click(self):
+ """
+ When the delete button is pressed
+ """
+ bible = None
if self.quickTab.isVisible():
bible = self.quickVersionComboBox.currentText()
elif self.advancedTab.isVisible():
@@ -488,8 +492,9 @@ class BibleMediaItem(MediaManagerItem):
if QtGui.QMessageBox.question(
self, UiStrings().ConfirmDelete,
translate('BiblesPlugin.MediaItem', 'Are you sure you want to completely delete "%s" Bible from '
- 'OpenLP?\n\nYou will need to re-import this Bible to use it again.') % bible,
- QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
+ 'OpenLP?\n\nYou will need to re-import this Bible to use it '
+ 'again.') % bible,
+ QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No:
return
self.plugin.manager.delete_bible(bible)
@@ -752,7 +757,7 @@ class BibleMediaItem(MediaManagerItem):
log.exception('The second_search_results does not have as many verses as the search_results.')
break
bible_text = '%s %d%s%d (%s, %s)' % (book, verse.chapter, verse_separator, verse.verse, version,
- second_version)
+ second_version)
else:
bible_text = '%s %d%s%d (%s)' % (book, verse.chapter, verse_separator, verse.verse, version)
bible_verse = QtGui.QListWidgetItem(bible_text)
@@ -840,6 +845,7 @@ class BibleMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.CanPreview)
service_item.add_capability(ItemCapabilities.CanLoop)
service_item.add_capability(ItemCapabilities.CanWordSplit)
+ service_item.add_capability(ItemCapabilities.CanEditTitle)
# Service Item: Title
service_item.title = create_separated_list(raw_title)
# Service Item: Theme
diff --git a/openlp/plugins/bibles/lib/versereferencelist.py b/openlp/plugins/bibles/lib/versereferencelist.py
index 1d3877d1d..7cbba68fb 100644
--- a/openlp/plugins/bibles/lib/versereferencelist.py
+++ b/openlp/plugins/bibles/lib/versereferencelist.py
@@ -94,5 +94,5 @@ class VerseReferenceList(object):
result = result + ', ' + version['permission']
result = result.rstrip()
if result.endswith(','):
- return result[:len(result)-1]
+ return result[:len(result) - 1]
return result
diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py
index eb7de530a..2065717cb 100644
--- a/openlp/plugins/custom/customplugin.py
+++ b/openlp/plugins/custom/customplugin.py
@@ -43,7 +43,7 @@ log = logging.getLogger(__name__)
__default_settings__ = {
'custom/db type': 'sqlite',
- 'custom/last search type': CustomSearch.Titles,
+ 'custom/last search type': CustomSearch.Titles,
'custom/display footer': True,
'custom/add custom from service': True
}
@@ -97,12 +97,12 @@ class CustomPlugin(Plugin):
"""
Called to define all translatable texts of the plugin
"""
- ## Name PluginList ##
+ # Name PluginList
self.text_strings[StringContent.Name] = {
'singular': translate('CustomPlugin', 'Custom Slide', 'name singular'),
'plural': translate('CustomPlugin', 'Custom Slides', 'name plural')
}
- ## Name for MediaDockManager, SettingsManager ##
+ # Name for MediaDockManager, SettingsManager
self.text_strings[StringContent.VisibleName] = {
'title': translate('CustomPlugin', 'Custom Slides', 'container title')
}
diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py
index afce4887b..e6834dafb 100644
--- a/openlp/plugins/custom/forms/editcustomslideform.py
+++ b/openlp/plugins/custom/forms/editcustomslideform.py
@@ -1,4 +1,3 @@
-#lint:disable
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
diff --git a/openlp/plugins/custom/lib/customxmlhandler.py b/openlp/plugins/custom/lib/customxmlhandler.py
index ca42a705b..3e1880055 100644
--- a/openlp/plugins/custom/lib/customxmlhandler.py
+++ b/openlp/plugins/custom/lib/customxmlhandler.py
@@ -51,7 +51,7 @@ from lxml import etree, objectify
log = logging.getLogger(__name__)
-#TODO: These classes need to be refactored into a single class.
+# TODO: These classes need to be refactored into a single class.
class CustomXMLBuilder(object):
"""
This class builds the XML used to describe songs.
diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py
index 693449530..08c31f53c 100644
--- a/openlp/plugins/images/imageplugin.py
+++ b/openlp/plugins/images/imageplugin.py
@@ -95,12 +95,12 @@ class ImagePlugin(Plugin):
"""
Called to define all translatable texts of the plugin.
"""
- ## Name PluginList ##
+ # Name PluginList
self.text_strings[StringContent.Name] = {
'singular': translate('ImagePlugin', 'Image', 'name singular'),
'plural': translate('ImagePlugin', 'Images', 'name plural')
}
- ## Name for MediaDockManager, SettingsManager ##
+ # Name for MediaDockManager, SettingsManager
self.text_strings[StringContent.VisibleName] = {'title': translate('ImagePlugin', 'Images', 'container title')}
# Middle Header Bar
tooltips = {
diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py
index b2eb5b816..d24a18434 100644
--- a/openlp/plugins/images/lib/mediaitem.py
+++ b/openlp/plugins/images/lib/mediaitem.py
@@ -550,6 +550,7 @@ class ImageMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.CanPreview)
service_item.add_capability(ItemCapabilities.CanLoop)
service_item.add_capability(ItemCapabilities.CanAppend)
+ service_item.add_capability(ItemCapabilities.CanEditTitle)
# force a nonexistent theme
service_item.theme = -1
missing_items_file_names = []
diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py
index 56d3a49f4..87d8e3311 100644
--- a/openlp/plugins/media/lib/mediaitem.py
+++ b/openlp/plugins/media/lib/mediaitem.py
@@ -95,7 +95,6 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
self.reset_action.setToolTip(UiStrings().ResetLiveBG)
self.automatic = UiStrings().Automatic
self.display_type_label.setText(translate('MediaPlugin.MediaItem', 'Use Player:'))
- #self.rebuild_players()
def required_icons(self):
"""
@@ -141,7 +140,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
if index == 0:
set_media_players(player)
else:
- set_media_players(player, player[index-1])
+ set_media_players(player, player[index - 1])
def on_reset_click(self):
"""
@@ -216,6 +215,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
if not self.media_controller.media_length(service_item):
return False
service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
+ service_item.add_capability(ItemCapabilities.CanEditTitle)
service_item.add_capability(ItemCapabilities.RequiresMedia)
if Settings().value(self.settings_section + '/media auto start') == QtCore.Qt.Checked:
service_item.will_auto_start = True
diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py
index 6cf241d1d..d0e082f53 100644
--- a/openlp/plugins/media/mediaplugin.py
+++ b/openlp/plugins/media/mediaplugin.py
@@ -73,12 +73,12 @@ class MediaPlugin(Plugin):
"""
Called to define all translatable texts of the plugin
"""
- ## Name PluginList ##
+ # Name PluginList
self.text_strings[StringContent.Name] = {
'singular': translate('MediaPlugin', 'Media', 'name singular'),
'plural': translate('MediaPlugin', 'Media', 'name plural')
}
- ## Name for MediaDockManager, SettingsManager ##
+ # Name for MediaDockManager, SettingsManager
self.text_strings[StringContent.VisibleName] = {
'title': translate('MediaPlugin', 'Media', 'container title')
}
diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py
index c55873c5f..584c1401f 100644
--- a/openlp/plugins/presentations/lib/impresscontroller.py
+++ b/openlp/plugins/presentations/lib/impresscontroller.py
@@ -377,8 +377,6 @@ class ImpressDocument(PresentationDocument):
Stop the presentation, remove from screen.
"""
log.debug('stop presentation OpenOffice')
- # deactivate should hide the screen according to docs, but doesn't
- #self.control.deactivate()
self.presentation.end()
self.control = None
diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py
index 1894cbf1f..5b503d50f 100644
--- a/openlp/plugins/presentations/lib/mediaitem.py
+++ b/openlp/plugins/presentations/lib/mediaitem.py
@@ -263,6 +263,7 @@ class PresentationMediaItem(MediaManagerItem):
file_type = os.path.splitext(filename)[1][1:]
if not self.display_type_combo_box.currentText():
return False
+ service_item.add_capability(ItemCapabilities.CanEditTitle)
if (file_type == 'pdf' or file_type == 'xps') and context != ServiceItemContext.Service:
service_item.add_capability(ItemCapabilities.CanMaintain)
service_item.add_capability(ItemCapabilities.CanPreview)
diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py
index 597b7d78b..5ed11d2ab 100644
--- a/openlp/plugins/presentations/lib/pdfcontroller.py
+++ b/openlp/plugins/presentations/lib/pdfcontroller.py
@@ -74,7 +74,7 @@ class PdfController(PresentationController):
runlog = ''
log.debug('testing program_path: %s', program_path)
try:
- runlog = check_output([program_path, '--help'], stderr=STDOUT)
+ runlog = check_output([program_path, '--help'], stderr=STDOUT)
except CalledProcessError as e:
runlog = e.output
except Exception:
@@ -183,7 +183,7 @@ class PdfDocument(PresentationDocument):
self.image_files = []
self.num_pages = -1
- def gs_get_resolution(self, size):
+ def gs_get_resolution(self, size):
"""
Only used when using ghostscript
Ghostscript can't scale automatically while keeping aspect like mupdf, so we need
@@ -204,19 +204,19 @@ class PdfDocument(PresentationDocument):
log.debug(' '.join(e.cmd))
log.debug(e.output)
# Extract the pdf resolution from output, the format is " Size: x: , y: "
- width = 0
- height = 0
+ width = 0.0
+ height = 0.0
for line in runlog.splitlines():
try:
- width = int(re.search('.*Size: x: (\d+\.?\d*), y: \d+.*', line.decode()).group(1))
- height = int(re.search('.*Size: x: \d+\.?\d*, y: (\d+\.?\d*).*', line.decode()).group(1))
+ width = float(re.search('.*Size: x: (\d+\.?\d*), y: \d+.*', line.decode()).group(1))
+ height = float(re.search('.*Size: x: \d+\.?\d*, y: (\d+\.?\d*).*', line.decode()).group(1))
break
except AttributeError:
- pass
+ continue
# Calculate the ratio from pdf to screen
if width > 0 and height > 0:
- width_ratio = size.right() / float(width)
- height_ratio = size.bottom() / float(height)
+ width_ratio = size.right() / width
+ height_ratio = size.bottom() / height
# return the resolution that should be used. 72 is default.
if width_ratio > height_ratio:
return int(height_ratio * 72)
@@ -236,7 +236,7 @@ class PdfDocument(PresentationDocument):
if os.path.isfile(os.path.join(self.get_temp_folder(), 'mainslide001.png')):
created_files = sorted(os.listdir(self.get_temp_folder()))
for fn in created_files:
- if os.path.isfile(os.path.join(self.get_temp_folder(), fn)):
+ if os.path.isfile(os.path.join(self.get_temp_folder(), fn)):
self.image_files.append(os.path.join(self.get_temp_folder(), fn))
self.num_pages = len(self.image_files)
return True
diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py
index d6447adce..09fdf2fcc 100644
--- a/openlp/plugins/presentations/lib/powerpointcontroller.py
+++ b/openlp/plugins/presentations/lib/powerpointcontroller.py
@@ -247,7 +247,7 @@ class PowerpointDocument(PresentationDocument):
Starts a presentation from the beginning.
"""
log.debug('start_presentation')
- #SlideShowWindow measures its size/position by points, not pixels
+ # SlideShowWindow measures its size/position by points, not pixels
try:
dpi = win32ui.GetActiveWindow().GetDC().GetDeviceCaps(88)
except win32ui.error:
diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py
index fd636b468..6c8d7fb8c 100644
--- a/openlp/plugins/presentations/lib/presentationcontroller.py
+++ b/openlp/plugins/presentations/lib/presentationcontroller.py
@@ -122,8 +122,10 @@ class PresentationDocument(object):
a file, e.g. thumbnails
"""
try:
- shutil.rmtree(self.get_thumbnail_folder())
- shutil.rmtree(self.get_temp_folder())
+ if os.path.exists(self.get_thumbnail_folder()):
+ shutil.rmtree(self.get_thumbnail_folder())
+ if os.path.exists(self.get_temp_folder()):
+ shutil.rmtree(self.get_temp_folder())
except OSError:
log.exception('Failed to delete presentation controller files')
diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py
index 7d5c81366..590289014 100644
--- a/openlp/plugins/presentations/lib/presentationtab.py
+++ b/openlp/plugins/presentations/lib/presentationtab.py
@@ -175,10 +175,10 @@ class PresentationTab(SettingsTab):
if pdf_program == '':
enable_pdf_program = 0
if pdf_program != Settings().value(self.settings_section + '/pdf_program'):
- Settings().setValue(self.settings_section + '/pdf_program', pdf_program)
+ Settings().setValue(self.settings_section + '/pdf_program', pdf_program)
changed = True
if enable_pdf_program != Settings().value(self.settings_section + '/enable_pdf_program'):
- Settings().setValue(self.settings_section + '/enable_pdf_program', enable_pdf_program)
+ Settings().setValue(self.settings_section + '/enable_pdf_program', enable_pdf_program)
changed = True
if changed:
self.settings_form.register_post_process('mediaitem_suffix_reset')
diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py
index de0a0c5a5..5e0d7395d 100644
--- a/openlp/plugins/presentations/presentationplugin.py
+++ b/openlp/plugins/presentations/presentationplugin.py
@@ -156,12 +156,12 @@ class PresentationPlugin(Plugin):
"""
Called to define all translatable texts of the plugin.
"""
- ## Name PluginList ##
+ # Name PluginList
self.text_strings[StringContent.Name] = {
'singular': translate('PresentationPlugin', 'Presentation', 'name singular'),
'plural': translate('PresentationPlugin', 'Presentations', 'name plural')
}
- ## Name for MediaDockManager, SettingsManager ##
+ # Name for MediaDockManager, SettingsManager
self.text_strings[StringContent.VisibleName] = {
'title': translate('PresentationPlugin', 'Presentations', 'container title')
}
diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py
index 393f08dd9..d3dc6e58a 100644
--- a/openlp/plugins/remotes/remoteplugin.py
+++ b/openlp/plugins/remotes/remoteplugin.py
@@ -92,12 +92,12 @@ class RemotesPlugin(Plugin):
"""
Called to define all translatable texts of the plugin
"""
- ## Name PluginList ##
+ # Name PluginList
self.text_strings[StringContent.Name] = {
'singular': translate('RemotePlugin', 'Remote', 'name singular'),
'plural': translate('RemotePlugin', 'Remotes', 'name plural')
}
- ## Name for MediaDockManager, SettingsManager ##
+ # Name for MediaDockManager, SettingsManager
self.text_strings[StringContent.VisibleName] = {
'title': translate('RemotePlugin', 'Remote', 'container title')
}
diff --git a/openlp/plugins/songs/forms/duplicatesongremovalform.py b/openlp/plugins/songs/forms/duplicatesongremovalform.py
index 22299cde5..c99dee4a7 100644
--- a/openlp/plugins/songs/forms/duplicatesongremovalform.py
+++ b/openlp/plugins/songs/forms/duplicatesongremovalform.py
@@ -31,6 +31,7 @@ The duplicate song removal logic for OpenLP.
"""
import logging
+import multiprocessing
import os
from PyQt4 import QtCore, QtGui
@@ -45,6 +46,18 @@ from openlp.plugins.songs.lib.songcompare import songs_probably_equal
log = logging.getLogger(__name__)
+def song_generator(songs):
+ """
+ This is a generator function to return tuples of two songs. When completed then all songs have once been returned
+ combined with any other songs.
+
+ :param songs: All songs in the database.
+ """
+ for outer_song_counter in range(len(songs) - 1):
+ for inner_song_counter in range(outer_song_counter + 1, len(songs)):
+ yield (songs[outer_song_counter], songs[inner_song_counter])
+
+
class DuplicateSongRemovalForm(OpenLPWizard, RegistryProperties):
"""
This is the Duplicate Song Removal Wizard. It provides functionality to search for and remove duplicate songs
@@ -114,7 +127,7 @@ class DuplicateSongRemovalForm(OpenLPWizard, RegistryProperties):
self.review_layout.addWidget(self.review_scroll_area)
self.review_page_id = self.addPage(self.review_page)
# Add a dummy page to the end, to prevent the finish button to appear and the next button do disappear on the
- #review page.
+ # review page.
self.dummy_page = QtGui.QWizardPage()
self.dummy_page_id = self.addPage(self.dummy_page)
@@ -167,24 +180,31 @@ class DuplicateSongRemovalForm(OpenLPWizard, RegistryProperties):
max_progress_count = max_songs * (max_songs - 1) // 2
self.duplicate_search_progress_bar.setMaximum(max_progress_count)
songs = self.plugin.manager.get_all_objects(Song)
- for outer_song_counter in range(max_songs - 1):
- for inner_song_counter in range(outer_song_counter + 1, max_songs):
- if songs_probably_equal(songs[outer_song_counter], songs[inner_song_counter]):
- duplicate_added = self.add_duplicates_to_song_list(
- songs[outer_song_counter], songs[inner_song_counter])
- if duplicate_added:
- self.found_duplicates_edit.appendPlainText(
- songs[outer_song_counter].title + " = " + songs[inner_song_counter].title)
- self.duplicate_search_progress_bar.setValue(self.duplicate_search_progress_bar.value() + 1)
- # The call to process_events() will keep the GUI responsive.
- self.application.process_events()
- if self.break_search:
- return
+ # Create a worker/process pool to check the songs.
+ process_number = max(1, multiprocessing.cpu_count() - 1)
+ pool = multiprocessing.Pool(process_number)
+ result = pool.imap_unordered(songs_probably_equal, song_generator(songs), 30)
+ # Do not accept any further tasks. Also this closes the processes if all tasks are done.
+ pool.close()
+ # While the processes are still working, start to look at the results.
+ for song_tuple in result:
+ self.duplicate_search_progress_bar.setValue(self.duplicate_search_progress_bar.value() + 1)
+ # The call to process_events() will keep the GUI responsive.
+ self.application.process_events()
+ if self.break_search:
+ pool.terminate()
+ return
+ if song_tuple is None:
+ continue
+ song1, song2 = song_tuple
+ duplicate_added = self.add_duplicates_to_song_list(song1, song2)
+ if duplicate_added:
+ self.found_duplicates_edit.appendPlainText(song1.title + " = " + song2.title)
self.review_total_count = len(self.duplicate_song_list)
- if self.review_total_count == 0:
- self.notify_no_duplicates()
- else:
+ if self.duplicate_song_list:
self.button(QtGui.QWizard.NextButton).show()
+ else:
+ self.notify_no_duplicates()
finally:
self.application.set_normal_cursor()
elif page_id == self.review_page_id:
@@ -217,12 +237,12 @@ class DuplicateSongRemovalForm(OpenLPWizard, RegistryProperties):
duplicate_added = False
for duplicate_group in self.duplicate_song_list:
# Skip the first song in the duplicate lists, since the first one has to be an earlier song.
- if search_song in duplicate_group and not duplicate_song in duplicate_group:
+ if search_song in duplicate_group and duplicate_song not in duplicate_group:
duplicate_group.append(duplicate_song)
duplicate_group_found = True
duplicate_added = True
break
- elif not search_song in duplicate_group and duplicate_song in duplicate_group:
+ elif search_song not in duplicate_group and duplicate_song in duplicate_group:
duplicate_group.append(search_song)
duplicate_group_found = True
duplicate_added = True
diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py
index b655c0f73..60c6eae78 100644
--- a/openlp/plugins/songs/forms/editsongform.py
+++ b/openlp/plugins/songs/forms/editsongform.py
@@ -675,14 +675,13 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog, RegistryProperties):
separator = parts.find(':')
if separator >= 0:
verse_name = parts[0:separator].strip()
- verse_num = parts[separator+1:].strip()
+ verse_num = parts[separator + 1:].strip()
else:
verse_name = parts
verse_num = '1'
verse_index = VerseType.from_loose_input(verse_name)
verse_tag = VerseType.tags[verse_index]
# Later we need to handle v1a as well.
- #regex = re.compile(r'(\d+\w.)')
regex = re.compile(r'\D*(\d+)\D*')
match = regex.match(verse_num)
if match:
diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py
index 038cff539..79a69a015 100644
--- a/openlp/plugins/songs/forms/editverseform.py
+++ b/openlp/plugins/songs/forms/editverseform.py
@@ -75,7 +75,7 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
text = self.verse_text_edit.toPlainText()
position = self.verse_text_edit.textCursor().position()
insert_string = '[---]'
- if position and text[position-1] != '\n':
+ if position and text[position - 1] != '\n':
insert_string = '\n' + insert_string
if position == len(text) or text[position] != '\n':
insert_string += '\n'
diff --git a/openlp/plugins/songs/forms/mediafilesdialog.py b/openlp/plugins/songs/forms/mediafilesdialog.py
index a0392e3db..3a1db39ed 100644
--- a/openlp/plugins/songs/forms/mediafilesdialog.py
+++ b/openlp/plugins/songs/forms/mediafilesdialog.py
@@ -66,8 +66,10 @@ class Ui_MediaFilesDialog(object):
def retranslateUi(self, media_files_dialog):
"""
Translate the UI on the fly.
+
+ :param media_files_dialog:
"""
media_files_dialog.setWindowTitle(translate('SongsPlugin.MediaFilesForm', 'Select Media File(s)'))
- self.select_label.setText(translate('SongsPlugin.MediaFilesForm',
- 'Select one or more audio files from the list below, and click OK to import them '
- 'into this song.'))
+ self.select_label.setText(translate('SongsPlugin.MediaFilesForm', 'Select one or more audio files from the '
+ 'list below, and click OK to import them '
+ 'into this song.'))
diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py
index 4e345b750..589da4d33 100644
--- a/openlp/plugins/songs/forms/songexportform.py
+++ b/openlp/plugins/songs/forms/songexportform.py
@@ -152,9 +152,9 @@ class SongExportForm(OpenLPWizard):
self.setWindowTitle(translate('SongsPlugin.ExportWizardForm', 'Song Export Wizard'))
self.title_label.setText(WizardStrings.HeaderStyle %
translate('OpenLP.Ui', 'Welcome to the Song Export Wizard'))
- self.information_label.setText(translate('SongsPlugin.ExportWizardForm', 'This wizard will help to'
- ' export your songs to the open and free OpenLyrics worship '
- 'song format.'))
+ self.information_label.setText(
+ translate('SongsPlugin.ExportWizardForm', 'This wizard will help to export your songs to the open and free '
+ 'OpenLyrics worship song format.'))
self.available_songs_page.setTitle(translate('SongsPlugin.ExportWizardForm', 'Select Songs'))
self.available_songs_page.setSubTitle(translate('SongsPlugin.ExportWizardForm',
'Check the songs you want to export.'))
diff --git a/openlp/plugins/songs/lib/cclifileimport.py b/openlp/plugins/songs/lib/cclifileimport.py
index 0866a1cc7..5c1fbdcb2 100644
--- a/openlp/plugins/songs/lib/cclifileimport.py
+++ b/openlp/plugins/songs/lib/cclifileimport.py
@@ -270,13 +270,13 @@ class CCLIFileImport(SongImport):
verse_text = ''
verse_start = False
else:
- #line_number=0, song title
+ # line_number=0, song title
if line_number == 0:
self.title = clean_line
line_number += 1
- #line_number=1, verses
+ # line_number=1, verses
elif line_number == 1:
- #line_number=1, ccli number, first line after verses
+ # line_number=1, ccli number, first line after verses
if clean_line.startswith('CCLI'):
line_number += 1
ccli_parts = clean_line.split(' ')
@@ -319,21 +319,21 @@ class CCLIFileImport(SongImport):
# last part. Add l so as to keep the CRLF
verse_text = verse_text + line
else:
- #line_number=2, copyright
+ # line_number=2, copyright
if line_number == 2:
line_number += 1
if clean_line.startswith('©'):
self.copyright = clean_line
else:
song_author = clean_line
- #n=3, authors
+ # n=3, authors
elif line_number == 3:
line_number += 1
if song_author:
self.copyright = clean_line
else:
song_author = clean_line
- #line_number=4, comments lines before last line
+ # line_number=4, comments lines before last line
elif line_number == 4 and not clean_line.startswith('CCL'):
self.comments += clean_line
# split on known separators
diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py
index e36021d04..1bbe5fed4 100644
--- a/openlp/plugins/songs/lib/ewimport.py
+++ b/openlp/plugins/songs/lib/ewimport.py
@@ -437,7 +437,7 @@ class EasyWorshipSongImport(SongImport):
elif field_desc.field_type == FieldType.Logical:
return field ^ 0x80 == 1
elif field_desc.field_type == FieldType.Memo or field_desc.field_type == FieldType.Blob:
- block_start, blob_size = struct.unpack_from('= MIN_BLOCK_SIZE:
length_of_equal_blocks += _op_length(element)
+
if length_of_equal_blocks >= MIN_BLOCK_SIZE:
- return True
+ return song1, song2
# Check 2: Similarity based on the relative length of the longest equal block.
# Calculate the length of the largest equal block of the diff set.
length_of_longest_equal_block = 0
for element in diff_no_typos:
if element[0] == "equal" and _op_length(element) > length_of_longest_equal_block:
length_of_longest_equal_block = _op_length(element)
- if length_of_equal_blocks >= MIN_BLOCK_SIZE or length_of_longest_equal_block > len(small) * 2 // 3:
- return True
+ if length_of_longest_equal_block > len(small) * 2 // 3:
+ return song1, song2
# Both checks failed. We assume the songs are not equal.
- return False
+ return None
def _op_length(opcode):
diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py
index 667afebdd..d516b5e02 100644
--- a/openlp/plugins/songs/lib/xml.py
+++ b/openlp/plugins/songs/lib/xml.py
@@ -675,6 +675,7 @@ class OpenLyrics(object):
sxml = SongXML()
verses = {}
verse_def_list = []
+ verse_order = self._text(properties.verseOrder).split(' ') if hasattr(properties, 'verseOrder') else []
try:
lyrics = song_xml.lyrics
except AttributeError:
@@ -717,13 +718,17 @@ class OpenLyrics(object):
else:
verses[(verse_tag, verse_number, lang, translit, verse_part)] = text
verse_def_list.append((verse_tag, verse_number, lang, translit, verse_part))
+ # Update verse order when the verse name has changed
+ if verse_def != verse_tag + verse_number + verse_part:
+ for i in range(len(verse_order)):
+ if verse_order[i] == verse_def:
+ verse_order[i] = verse_tag + verse_number + verse_part
# We have to use a list to keep the order, as dicts are not sorted.
for verse in verse_def_list:
sxml.add_verse_to_lyrics(verse[0], verse[1], verses[verse], verse[2])
song_obj.lyrics = str(sxml.extract_xml(), 'utf-8')
# Process verse order
- if hasattr(properties, 'verseOrder'):
- song_obj.verse_order = self._text(properties.verseOrder)
+ song_obj.verse_order = ' '.join(verse_order)
def _process_songbooks(self, properties, song):
"""
diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py
index 1c000338c..b1ddaf412 100644
--- a/openlp/plugins/songs/songsplugin.py
+++ b/openlp/plugins/songs/songsplugin.py
@@ -132,7 +132,7 @@ class SongsPlugin(Plugin):
)
import_menu.addAction(self.import_songselect_item)
- def add_export_menu_Item(self, export_menu):
+ def add_export_menu_item(self, export_menu):
"""
Give the Songs plugin the opportunity to add items to the **Export** menu.
@@ -261,12 +261,12 @@ class SongsPlugin(Plugin):
"""
Called to define all translatable texts of the plugin
"""
- ## Name PluginList ##
+ # Name PluginList
self.text_strings[StringContent.Name] = {
'singular': translate('SongsPlugin', 'Song', 'name singular'),
'plural': translate('SongsPlugin', 'Songs', 'name plural')
}
- ## Name for MediaDockManager, SettingsManager ##
+ # Name for MediaDockManager, SettingsManager
self.text_strings[StringContent.VisibleName] = {
'title': translate('SongsPlugin', 'Songs', 'container title')
}
diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py
index 4d38de6dd..8c0fc5762 100644
--- a/openlp/plugins/songusage/songusageplugin.py
+++ b/openlp/plugins/songusage/songusageplugin.py
@@ -246,12 +246,12 @@ class SongUsagePlugin(Plugin):
"""
Called to define all translatable texts of the plugin
"""
- ## Name PluginList ##
+ # Name PluginList
self.text_strings[StringContent.Name] = {
'singular': translate('SongUsagePlugin', 'SongUsage', 'name singular'),
'plural': translate('SongUsagePlugin', 'SongUsage', 'name plural')
}
- ## Name for MediaDockManager, SettingsManager ##
+ # Name for MediaDockManager, SettingsManager
self.text_strings[StringContent.VisibleName] = {
'title': translate('SongUsagePlugin', 'SongUsage', 'container title')
}
diff --git a/scripts/jenkins_script.py b/scripts/jenkins_script.py
index 386ab69ef..aaee9a71b 100644
--- a/scripts/jenkins_script.py
+++ b/scripts/jenkins_script.py
@@ -40,6 +40,7 @@ You can look up the token in the Branch-01-Pull job configuration or ask in IRC.
"""
from optparse import OptionParser
+import re
from requests.exceptions import HTTPError
from subprocess import Popen, PIPE
import sys
@@ -49,6 +50,9 @@ from jenkins import Jenkins
JENKINS_URL = 'http://ci.openlp.org/'
+REPO_REGEX = r'(.*/+)(~.*)'
+# Allows us to black list token. So when we change the token, we can display a proper message to the user.
+OLD_TOKENS = []
class OpenLPJobs(object):
@@ -59,9 +63,20 @@ class OpenLPJobs(object):
Branch_Functional = 'Branch-02-Functional-Tests'
Branch_Interface = 'Branch-03-Interface-Tests'
Branch_Windows = 'Branch-04-Windows_Tests'
- Branch_PEP = 'Branch-05-Code-Analysis'
+ Branch_PEP = 'Branch-05a-Code_Analysis'
+ Branch_Coverage = 'Branch-05b-Test_Coverage'
- Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows, Branch_PEP]
+ Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows, Branch_PEP, Branch_Coverage]
+
+
+class Colour(object):
+ """
+ This class holds values which can be used to print coloured text.
+ """
+ RED_START = '\033[1;31m'
+ RED_END = '\033[1;m'
+ GREEN_START = '\033[1;32m'
+ GREEN_END = '\033[1;m'
class JenkinsTrigger(object):
@@ -79,14 +94,25 @@ class JenkinsTrigger(object):
"""
Ask our jenkins server to build the "Branch-01-Pull" job.
"""
- self.jenkins_instance.job(OpenLPJobs.Branch_Pull).build({'BRANCH_NAME': self.repo_name}, token=self.token)
+ bzr = Popen(('bzr', 'whoami'), stdout=PIPE, stderr=PIPE)
+ raw_output, error = bzr.communicate()
+ # We just want the name (not the email).
+ name = ' '.join(raw_output.decode().split()[:-1])
+ cause = 'Build triggered by %s (%s)' % (name, self.repo_name)
+ self.jenkins_instance.job(OpenLPJobs.Branch_Pull).build(
+ {'BRANCH_NAME': self.repo_name, 'cause': cause}, token=self.token)
def print_output(self):
"""
Print the status information of the build tirggered.
"""
- print("Add this to your merge proposal:")
- print("--------------------------------")
+ print('Add this to your merge proposal:')
+ print('--------------------------------')
+ bzr = Popen(('bzr', 'revno'), stdout=PIPE, stderr=PIPE)
+ raw_output, error = bzr.communicate()
+ revno = raw_output.decode().strip()
+ print('%s (revision %s)' % (get_repo_name(), revno))
+
for job in OpenLPJobs.Jobs:
self.__print_build_info(job)
@@ -107,17 +133,17 @@ class JenkinsTrigger(object):
"""
job = self.jenkins_instance.job(job_name)
while job.info['inQueue']:
- # Give other processes the possibility to take over. Like Thread.yield().
- time.sleep(0)
+ time.sleep(1)
build = job.last_build
build.wait()
- result_string = build.info['result']
+ if build.info['result'] == 'SUCCESS':
+ # Make 'SUCCESS' green.
+ result_string = '%s%s%s' % (Colour.GREEN_START, build.info['result'], Colour.GREEN_END)
+ else:
+ # Make 'FAILURE' red.
+ result_string = '%s%s%s' % (Colour.RED_START, build.info['result'], Colour.RED_END)
url = build.info['url']
print('[%s] %s' % (result_string, url))
- # On failure open the browser.
- #if result_string == "FAILURE":
- # url += 'console'
- # Popen(('xdg-open', url), stderr=PIPE)
def get_repo_name():
@@ -139,46 +165,41 @@ def get_repo_name():
for line in output_list:
# Check if it is remote branch.
if 'push branch' in line:
- repo_name = line.replace('push branch: bzr+ssh://bazaar.launchpad.net/', 'lp:')
- break
+ match = re.match(REPO_REGEX, line)
+ if match:
+ repo_name = 'lp:%s' % match.group(2)
+ break
elif 'checkout of branch' in line:
- repo_name = line.replace('checkout of branch: bzr+ssh://bazaar.launchpad.net/', 'lp:')
- break
- repo_name = repo_name.strip('/')
-
- # Did we find the branch name?
- if not repo_name:
- for line in output_list:
- # Check if the branch was pushed.
- if 'Shared repository with trees (format: 2a)' in line:
- print('Not a branch. cd to a branch.')
- return
- print('Not a branch. Have you pushed it to launchpad?')
- return
- return repo_name
+ match = re.match(REPO_REGEX, line)
+ if match:
+ repo_name = 'lp:%s' % match.group(2)
+ break
+ return repo_name.strip('/')
def main():
usage = 'Usage: python %prog TOKEN [options]'
parser = OptionParser(usage=usage)
- parser.add_option('-d', '--disable-output', dest='enable_output', action="store_false", default=True,
+ parser.add_option('-d', '--disable-output', dest='enable_output', action='store_false', default=True,
help='Disable output.')
- parser.add_option('-b', '--open-browser', dest='open_browser', action="store_true", default=False,
+ parser.add_option('-b', '--open-browser', dest='open_browser', action='store_true', default=False,
help='Opens the jenkins page in your browser.')
- #parser.add_option('-e', '--open-browser-on-error', dest='open_browser_on_error', action="store_true",
- # default=False, help='Opens the jenkins page in your browser in case a test fails.')
options, args = parser.parse_args(sys.argv)
if len(args) == 2:
if not get_repo_name():
+ print('Not a branch. Have you pushed it to launchpad? Did you cd to the branch?')
return
token = args[-1]
+ if token in OLD_TOKENS:
+ print('Your token is not valid anymore. Get the most recent one.')
+ return
jenkins_trigger = JenkinsTrigger(token)
try:
jenkins_trigger.trigger_build()
except HTTPError as e:
- print("Wrong token.")
+ print('Wrong token.')
return
# Open the browser before printing the output.
if options.open_browser:
diff --git a/tests/functional/openlp_core_common/test_init.py b/tests/functional/openlp_core_common/test_common.py
similarity index 76%
rename from tests/functional/openlp_core_common/test_init.py
rename to tests/functional/openlp_core_common/test_common.py
index dcc4fe32a..90b7d0520 100644
--- a/tests/functional/openlp_core_common/test_init.py
+++ b/tests/functional/openlp_core_common/test_common.py
@@ -32,12 +32,13 @@ Functional tests to test the AppLocation class and related methods.
from unittest import TestCase
-from openlp.core.common import de_hump
+from openlp.core.common import de_hump, trace_error_handler
+from tests.functional import MagicMock, patch
-class TestInitFunctions(TestCase):
+class TestCommonFunctions(TestCase):
"""
- A test suite to test out various functions in the __init__ class.
+ A test suite to test out various functions in the openlp.core.common module.
"""
def de_hump_conversion_test(self):
"""
@@ -64,3 +65,19 @@ class TestInitFunctions(TestCase):
# THEN: the new string should be converted to python format
self.assertTrue(new_string == "my_class", 'The class name should have been preserved')
+
+ def trace_error_handler_test(self):
+ """
+ Test the trace_error_handler() method
+ """
+ # GIVEN: Mocked out objects
+ with patch('openlp.core.common.traceback') as mocked_traceback:
+ mocked_traceback.extract_stack.return_value = [('openlp.fake', 56, None, 'trace_error_handler_test')]
+ mocked_logger = MagicMock()
+
+ # WHEN: trace_error_handler() is called
+ trace_error_handler(mocked_logger)
+
+ # THEN: The mocked_logger.error() method should have been called with the correct parameters
+ mocked_logger.error.assert_called_with('OpenLP Error trace\n File openlp.fake at line 56 \n\t called trace_error_handler_test')
+
diff --git a/tests/functional/openlp_core_common/test_registryproperties.py b/tests/functional/openlp_core_common/test_registryproperties.py
index fa8a2b540..c2e430a95 100644
--- a/tests/functional/openlp_core_common/test_registryproperties.py
+++ b/tests/functional/openlp_core_common/test_registryproperties.py
@@ -52,7 +52,7 @@ class TestRegistryProperties(TestCase, RegistryProperties):
# GIVEN an Empty Registry
# WHEN there is no Application
# THEN the application should be none
- self.assertEquals(self.application, None, 'The application value should be None')
+ self.assertEqual(self.application, None, 'The application value should be None')
def application_test(self):
"""
@@ -63,4 +63,4 @@ class TestRegistryProperties(TestCase, RegistryProperties):
# WHEN the application is registered
Registry().register('application', application)
# THEN the application should be none
- self.assertEquals(self.application, application, 'The application value should match')
+ self.assertEqual(self.application, application, 'The application value should match')
diff --git a/tests/functional/openlp_core_lib/test_db.py b/tests/functional/openlp_core_lib/test_db.py
index f11292209..071a3904b 100644
--- a/tests/functional/openlp_core_lib/test_db.py
+++ b/tests/functional/openlp_core_lib/test_db.py
@@ -50,8 +50,8 @@ class TestDB(TestCase):
"""
# GIVEN: Mocked out SQLAlchemy calls and return objects, and an in-memory SQLite database URL
with patch('openlp.core.lib.db.create_engine') as mocked_create_engine, \
- patch('openlp.core.lib.db.MetaData') as MockedMetaData, \
- patch('openlp.core.lib.db.sessionmaker') as mocked_sessionmaker, \
+ patch('openlp.core.lib.db.MetaData') as MockedMetaData, \
+ patch('openlp.core.lib.db.sessionmaker') as mocked_sessionmaker, \
patch('openlp.core.lib.db.scoped_session') as mocked_scoped_session:
mocked_engine = MagicMock()
mocked_metadata = MagicMock()
diff --git a/tests/functional/openlp_core_lib/test_image_manager.py b/tests/functional/openlp_core_lib/test_image_manager.py
index e9968e1c7..37b6d6fdd 100644
--- a/tests/functional/openlp_core_lib/test_image_manager.py
+++ b/tests/functional/openlp_core_lib/test_image_manager.py
@@ -30,12 +30,16 @@
Package to test the openlp.core.ui package.
"""
import os
+import time
+from threading import Lock
from unittest import TestCase
from PyQt4 import QtGui
from openlp.core.common import Registry
from openlp.core.lib import ImageManager, ScreenList
+from openlp.core.lib.imagemanager import Priority
+from tests.functional import patch
from tests.helpers.testmixin import TestMixin
TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'resources'))
@@ -51,6 +55,8 @@ class TestImageManager(TestCase, TestMixin):
self.get_application()
ScreenList.create(self.app.desktop())
self.image_manager = ImageManager()
+ self.lock = Lock()
+ self.sleep_time = 0.1
def tearDown(self):
"""
@@ -82,3 +88,87 @@ class TestImageManager(TestCase, TestMixin):
with self.assertRaises(KeyError) as context:
self.image_manager.get_image(TEST_PATH, 'church1.jpg')
self.assertNotEquals(context.exception, '', 'KeyError exception should have been thrown for missing image')
+
+ def process_cache_test(self):
+ """
+ Test the process_cache method
+ """
+ with patch('openlp.core.lib.imagemanager.resize_image') as mocked_resize_image, \
+ patch('openlp.core.lib.imagemanager.image_to_byte') as mocked_image_to_byte:
+ # GIVEN: Mocked functions
+ mocked_resize_image.side_effect = self.mocked_resize_image
+ mocked_image_to_byte.side_effect = self.mocked_image_to_byte
+ image1 = 'church.jpg'
+ image2 = 'church2.jpg'
+ image3 = 'church3.jpg'
+ image4 = 'church4.jpg'
+
+ # WHEN: Add the images. Then get the lock (=queue can not be processed).
+ self.lock.acquire()
+ self.image_manager.add_image(TEST_PATH, image1, None)
+ self.image_manager.add_image(TEST_PATH, image2, None)
+
+ # THEN: All images have been added to the queue, and only the first image is not be in the list anymore, but
+ # is being processed (see mocked methods/functions).
+ # Note: Priority.Normal means, that the resize_image() was not completed yet (because afterwards the #
+ # priority is adjusted to Priority.Lowest).
+ self.assertEqual(self.get_image_priority(image1), Priority.Normal,
+ "image1's priority should be 'Priority.Normal'")
+ self.assertEqual(self.get_image_priority(image2), Priority.Normal,
+ "image2's priority should be 'Priority.Normal'")
+
+ # WHEN: Add more images.
+ self.image_manager.add_image(TEST_PATH, image3, None)
+ self.image_manager.add_image(TEST_PATH, image4, None)
+ # Allow the queue to process.
+ self.lock.release()
+ # Request some "data".
+ image_bytes = self.image_manager.get_image_bytes(TEST_PATH, image4)
+ image_object = self.image_manager.get_image(TEST_PATH, image3)
+ # Now the mocked methods/functions do not have to sleep anymore.
+ self.sleep_time = 0
+ # Wait for the queue to finish.
+ while not self.image_manager._conversion_queue.empty():
+ time.sleep(0.1)
+ # Because empty() is not reliable, wait a litte; just to make sure.
+ time.sleep(0.1)
+ # THEN: The images' priority reflect how they were processed.
+ self.assertEqual(self.image_manager._conversion_queue.qsize(), 0, "The queue should be empty.")
+ self.assertEqual(self.get_image_priority(image1), Priority.Lowest,
+ "The image should have not been requested (=Lowest)")
+ self.assertEqual(self.get_image_priority(image2), Priority.Lowest,
+ "The image should have not been requested (=Lowest)")
+ self.assertEqual(self.get_image_priority(image3), Priority.Low,
+ "Only the QImage should have been requested (=Low).")
+ self.assertEqual(self.get_image_priority(image4), Priority.Urgent,
+ "The image bytes should have been requested (=Urgent).")
+
+ def get_image_priority(self, image):
+ """
+ This is a help method to get the priority of the given image out of the image_manager's cache.
+
+ NOTE: This requires, that the image has been added to the image manager using the *TEST_PATH*.
+
+ :param image: The name of the image. E. g. ``image1``
+ """
+ return self.image_manager._cache[(TEST_PATH, image)].priority
+
+ def mocked_resize_image(self, *args):
+ """
+ This is a mocked method, so that we can control the work flow of the image manager.
+ """
+ self.lock.acquire()
+ self.lock.release()
+ # The sleep time is adjusted in the test case.
+ time.sleep(self.sleep_time)
+ return QtGui.QImage()
+
+ def mocked_image_to_byte(self, *args):
+ """
+ This is a mocked method, so that we can control the work flow of the image manager.
+ """
+ self.lock.acquire()
+ self.lock.release()
+ # The sleep time is adjusted in the test case.
+ time.sleep(self.sleep_time)
+ return ''
\ No newline at end of file
diff --git a/tests/functional/openlp_core_lib/test_pluginmanager.py b/tests/functional/openlp_core_lib/test_pluginmanager.py
index ce5c240b2..d98a522b8 100644
--- a/tests/functional/openlp_core_lib/test_pluginmanager.py
+++ b/tests/functional/openlp_core_lib/test_pluginmanager.py
@@ -212,9 +212,9 @@ class TestPluginManager(TestCase):
# WHEN: We run hook_export_menu()
plugin_manager.hook_export_menu()
- # THEN: The add_export_menu_Item() method should not have been called
- self.assertEqual(0, mocked_plugin.add_export_menu_Item.call_count,
- 'The add_export_menu_Item() method should not have been called.')
+ # THEN: The add_export_menu_item() method should not have been called
+ self.assertEqual(0, mocked_plugin.add_export_menu_item.call_count,
+ 'The add_export_menu_item() method should not have been called.')
def hook_export_menu_with_active_plugin_test(self):
"""
@@ -229,8 +229,8 @@ class TestPluginManager(TestCase):
# WHEN: We run hook_export_menu()
plugin_manager.hook_export_menu()
- # THEN: The add_export_menu_Item() method should have been called
- mocked_plugin.add_export_menu_Item.assert_called_with(self.mocked_main_window.file_export_menu)
+ # THEN: The add_export_menu_item() method should have been called
+ mocked_plugin.add_export_menu_item.assert_called_with(self.mocked_main_window.file_export_menu)
def hook_upgrade_plugin_settings_with_disabled_plugin_test(self):
"""
@@ -264,7 +264,7 @@ class TestPluginManager(TestCase):
# WHEN: We run hook_upgrade_plugin_settings()
plugin_manager.hook_upgrade_plugin_settings(settings)
- # THEN: The add_export_menu_Item() method should have been called
+ # THEN: The add_export_menu_item() method should have been called
mocked_plugin.upgrade_settings.assert_called_with(settings)
def hook_tools_menu_with_disabled_plugin_test(self):
diff --git a/tests/functional/openlp_core_lib/test_renderer.py b/tests/functional/openlp_core_lib/test_renderer.py
index 51e915e3f..8814a21a0 100644
--- a/tests/functional/openlp_core_lib/test_renderer.py
+++ b/tests/functional/openlp_core_lib/test_renderer.py
@@ -49,7 +49,7 @@ class TestRenderer(TestCase):
def setUp(self):
"""
- Set up the components need for all tests.
+ Set up the components need for all tests
"""
# Mocked out desktop object
self.desktop = MagicMock()
@@ -67,7 +67,7 @@ class TestRenderer(TestCase):
def initial_renderer_test(self):
"""
- Test the initial renderer state .
+ Test the initial renderer state
"""
# GIVEN: A new renderer instance.
renderer = Renderer()
@@ -77,7 +77,7 @@ class TestRenderer(TestCase):
def default_screen_layout_test(self):
"""
- Test the default layout calculations.
+ Test the default layout calculations
"""
# GIVEN: A new renderer instance.
renderer = Renderer()
@@ -87,3 +87,35 @@ class TestRenderer(TestCase):
self.assertEqual(renderer.height, 768, 'The base renderer should be a live controller')
self.assertEqual(renderer.screen_ratio, 0.75, 'The base renderer should be a live controller')
self.assertEqual(renderer.footer_start, 691, 'The base renderer should be a live controller')
+
+ def _get_start_tags_test(self):
+ """
+ Test the _get_start_tags() method
+ """
+ # GIVEN: A new renderer instance. Broken raw_text (missing closing tags).
+ renderer = Renderer()
+ given_raw_text = '{st}{r}Text text text'
+ expected_tuple = ('{st}{r}Text text text{/r}{/st}', '{st}{r}',
+ '')
+
+ # WHEN:
+ result = renderer._get_start_tags(given_raw_text)
+
+ # THEN: Check if the correct tuple is returned.
+ self.assertEqual(result, expected_tuple), 'A tuple should be returned containing the text with correct ' \
+ 'tags, the opening tags, and the opening html tags.'
+
+ def _word_split_test(self):
+ """
+ Test the _word_split() method
+ """
+ # GIVEN: A line of text
+ renderer = Renderer()
+ given_line = 'beginning asdf \n end asdf'
+ expected_words = ['beginning', 'asdf', 'end', 'asdf']
+
+ # WHEN: Split the line
+ result_words = renderer._words_split(given_line)
+
+ # THEN: The word lists should be the same.
+ self.assertListEqual(result_words, expected_words)
diff --git a/tests/functional/openlp_core_lib/test_ui.py b/tests/functional/openlp_core_lib/test_ui.py
index babc94a81..91d59ab5a 100644
--- a/tests/functional/openlp_core_lib/test_ui.py
+++ b/tests/functional/openlp_core_lib/test_ui.py
@@ -81,3 +81,92 @@ class TestUi(TestCase):
self.assertIsInstance(btnbox, QtGui.QDialogButtonBox)
self.assertEqual(1, len(btnbox.buttons()))
self.assertEqual(QtGui.QDialogButtonBox.HelpRole, btnbox.buttonRole(btnbox.buttons()[0]))
+
+ def test_create_button(self):
+ """
+ Test creating a button
+ """
+ # GIVEN: A dialog
+ dialog = QtGui.QDialog()
+
+ # WHEN: We create the button
+ btn = create_button(dialog, 'my_btn')
+
+ # THEN: We should get a button with a name
+ self.assertIsInstance(btn, QtGui.QPushButton)
+ self.assertEqual('my_btn', btn.objectName())
+ self.assertTrue(btn.isEnabled())
+
+ # WHEN: We create a button with some attributes
+ btn = create_button(dialog, 'my_btn', text='Hello', tooltip='How are you?', enabled=False)
+
+ # THEN: We should get a button with those attributes
+ self.assertIsInstance(btn, QtGui.QPushButton)
+ self.assertEqual('Hello', btn.text())
+ self.assertEqual('How are you?', btn.toolTip())
+ self.assertFalse(btn.isEnabled())
+
+ # WHEN: We create a toolbutton
+ btn = create_button(dialog, 'my_btn', btn_class='toolbutton')
+
+ # THEN: We should get a toolbutton
+ self.assertIsInstance(btn, QtGui.QToolButton)
+ self.assertEqual('my_btn', btn.objectName())
+ self.assertTrue(btn.isEnabled())
+
+ def test_create_valign_selection_widgets(self):
+ """
+ Test creating a combo box for valign selection
+ """
+ # GIVEN: A dialog
+ dialog = QtGui.QDialog()
+
+ # WHEN: We create the widgets
+ label, combo = create_valign_selection_widgets(dialog)
+
+ # THEN: We should get a label and a combobox.
+ self.assertEqual(translate('OpenLP.Ui', '&Vertical Align:'), label.text())
+ self.assertIsInstance(combo, QtGui.QComboBox)
+ self.assertEqual(combo, label.buddy())
+ for text in [UiStrings().Top, UiStrings().Middle, UiStrings().Bottom]:
+ self.assertTrue(combo.findText(text) >= 0)
+
+ def test_create_horizontal_adjusting_combo_box(self):
+ """
+ Test creating a horizontal adjusting combo box
+ """
+ # GIVEN: A dialog
+ dialog = QtGui.QDialog()
+
+ # WHEN: We create the combobox
+ combo = create_horizontal_adjusting_combo_box(dialog, 'combo1')
+
+ # THEN: We should get a ComboBox
+ self.assertIsInstance(combo, QtGui.QComboBox)
+ self.assertEqual('combo1', combo.objectName())
+ self.assertEqual(QtGui.QComboBox.AdjustToMinimumContentsLength, combo.sizeAdjustPolicy())
+
+ def test_create_action(self):
+ """
+ Test creating an action
+ """
+ # GIVEN: A dialog
+ dialog = QtGui.QDialog()
+
+ # WHEN: We create an action
+ action = create_action(dialog, 'my_action')
+
+ # THEN: We should get a QAction
+ self.assertIsInstance(action, QtGui.QAction)
+ self.assertEqual('my_action', action.objectName())
+
+ # WHEN: We create an action with some properties
+ action = create_action(dialog, 'my_action', text='my text', icon=':/wizards/wizard_firsttime.bmp',
+ tooltip='my tooltip', statustip='my statustip')
+
+ # THEN: These properties should be set
+ self.assertIsInstance(action, QtGui.QAction)
+ self.assertEqual('my text', action.text())
+ self.assertIsInstance(action.icon(), QtGui.QIcon)
+ self.assertEqual('my tooltip', action.toolTip())
+ self.assertEqual('my statustip', action.statusTip())
diff --git a/tests/functional/openlp_core_ui/test_firsttimeform.py b/tests/functional/openlp_core_ui/test_firsttimeform.py
new file mode 100644
index 000000000..9fc6f5137
--- /dev/null
+++ b/tests/functional/openlp_core_ui/test_firsttimeform.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2014 Raoul Snyman #
+# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+"""
+Package to test the openlp.core.ui.firsttimeform package.
+"""
+from unittest import TestCase
+
+from tests.functional import MagicMock
+
+from tests.helpers.testmixin import TestMixin
+from openlp.core.common import Registry
+from openlp.core.ui.firsttimeform import FirstTimeForm
+
+
+class TestFirstTimeForm(TestCase, TestMixin):
+
+ def setUp(self):
+ screens = MagicMock()
+ self.get_application()
+ Registry.create()
+ Registry().register('application', self.app)
+ self.first_time_form = FirstTimeForm(screens)
+
+ def test_access_to_config(self):
+ """
+ Test if we can access the First Time Form's config file
+ """
+ # GIVEN A new First Time Form instance.
+
+ # WHEN The default First Time Form is built.
+
+ # THEN The First Time Form web configuration file should be accessable.
+ self.assertTrue(self.first_time_form.web_access,
+ 'First Time Wizard\'s web configuration file should be available')
+
+ def test_parsable_config(self):
+ """
+ Test if the First Time Form's config file is parsable
+ """
+ # GIVEN A new First Time Form instance.
+
+ # WHEN The default First Time Form is built.
+
+ # THEN The First Time Form web configuration file should be parsable
+ self.assertTrue(self.first_time_form.songs_url,
+ 'First Time Wizard\'s web configuration file should be parsable')
diff --git a/tests/functional/openlp_core_ui/test_maindisplay.py b/tests/functional/openlp_core_ui/test_maindisplay.py
index dffc6ec16..b1a4dc7f7 100644
--- a/tests/functional/openlp_core_ui/test_maindisplay.py
+++ b/tests/functional/openlp_core_ui/test_maindisplay.py
@@ -79,3 +79,31 @@ class TestMainDisplay(TestCase):
# THEN: The controller should not be a live controller.
self.assertEqual(main_display.is_live, True, 'The main display should be a live controller')
+
+ def set_transparency_test(self):
+ """
+ Test creating an instance of the MainDisplay class
+ """
+ # GIVEN: get an instance of MainDisplay
+ display = MagicMock()
+ main_display = MainDisplay(display)
+
+ # WHEN: We enable transparency
+ main_display.set_transparency(True)
+
+ # THEN: There should be a Stylesheet
+ self.assertEqual('QGraphicsView {background: transparent; border: 0px;}', main_display.styleSheet(),
+ 'MainDisplay instance should be transparent')
+ self.assertFalse(main_display.autoFillBackground(),
+ 'MainDisplay instance should be without background auto fill')
+ self.assertTrue(main_display.testAttribute(QtCore.Qt.WA_TranslucentBackground),
+ 'MainDisplay hasnt translucent background')
+
+ # WHEN: We disable transparency
+ main_display.set_transparency(False)
+
+ # THEN: The Stylesheet should be empty
+ self.assertEqual('QGraphicsView {}', main_display.styleSheet(),
+ 'MainDisplay instance should not be transparent')
+ self.assertFalse(main_display.testAttribute(QtCore.Qt.WA_TranslucentBackground),
+ 'MainDisplay hasnt translucent background')
diff --git a/tests/functional/openlp_core_ui/test_mainwindow.py b/tests/functional/openlp_core_ui/test_mainwindow.py
new file mode 100644
index 000000000..0b17828b9
--- /dev/null
+++ b/tests/functional/openlp_core_ui/test_mainwindow.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2014 Raoul Snyman #
+# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+"""
+Package to test openlp.core.ui.mainwindow package.
+"""
+import os
+
+from unittest import TestCase
+
+from openlp.core.ui.mainwindow import MainWindow
+from openlp.core.common.registry import Registry
+from tests.utils.constants import TEST_RESOURCES_PATH
+from tests.helpers.testmixin import TestMixin
+from tests.functional import MagicMock, patch
+
+
+class TestMainWindow(TestCase, TestMixin):
+
+ def setUp(self):
+ Registry.create()
+ self.registry = Registry()
+ self.get_application()
+ # Mock cursor busy/normal methods.
+ self.app.set_busy_cursor = MagicMock()
+ self.app.set_normal_cursor = MagicMock()
+ self.app.args = []
+ Registry().register('application', self.app)
+ # Mock classes and methods used by mainwindow.
+ with patch('openlp.core.ui.mainwindow.SettingsForm') as mocked_settings_form, \
+ patch('openlp.core.ui.mainwindow.ImageManager') as mocked_image_manager, \
+ patch('openlp.core.ui.mainwindow.LiveController') as mocked_live_controller, \
+ patch('openlp.core.ui.mainwindow.PreviewController') as mocked_preview_controller, \
+ patch('openlp.core.ui.mainwindow.OpenLPDockWidget') as mocked_dock_widget, \
+ patch('openlp.core.ui.mainwindow.QtGui.QToolBox') as mocked_q_tool_box_class, \
+ patch('openlp.core.ui.mainwindow.QtGui.QMainWindow.addDockWidget') as mocked_add_dock_method, \
+ patch('openlp.core.ui.mainwindow.ThemeManager') as mocked_theme_manager, \
+ patch('openlp.core.ui.mainwindow.Renderer') as mocked_renderer:
+ self.main_window = MainWindow()
+
+ def tearDown(self):
+ del self.main_window
+
+ def cmd_line_file_test(self):
+ """
+ Test that passing a service file from the command line loads the service.
+ """
+ # GIVEN a service as an argument to openlp
+ service = os.path.join(TEST_RESOURCES_PATH, 'service', 'test.osz')
+ self.main_window.arguments = [service]
+ with patch('openlp.core.ui.servicemanager.ServiceManager.load_file') as mocked_load_path:
+
+ # WHEN the argument is processed
+ self.main_window.open_cmd_line_files()
+
+ # THEN the service from the arguments is loaded
+ mocked_load_path.assert_called_with(service), 'load_path should have been called with the service\'s path'
+
+ def cmd_line_arg_test(self):
+ """
+ Test that passing a non service file does nothing.
+ """
+ # GIVEN a non service file as an argument to openlp
+ service = os.path.join('openlp.py')
+ self.main_window.arguments = [service]
+ with patch('openlp.core.ui.servicemanager.ServiceManager.load_file') as mocked_load_path:
+
+ # WHEN the argument is processed
+ self.main_window.open_cmd_line_files()
+
+ # THEN the file should not be opened
+ assert not mocked_load_path.called, 'load_path should not have been called'
diff --git a/tests/functional/openlp_plugins/bibles/test_http.py b/tests/functional/openlp_plugins/bibles/test_http.py
index b9bb8f11c..05a59a509 100644
--- a/tests/functional/openlp_plugins/bibles/test_http.py
+++ b/tests/functional/openlp_plugins/bibles/test_http.py
@@ -180,4 +180,4 @@ class TestBSExtract(TestCase):
'http://m.bibleserver.com/overlay/selectBook?translation=NIV')
self.assertFalse(self.mock_log.error.called, 'log.error should not have been called')
self.assertFalse(self.mock_send_error_message.called, 'send_error_message should not have been called')
- self.assertEquals(result, ['Genesis', 'Leviticus'])
+ self.assertEqual(result, ['Genesis', 'Leviticus'])
diff --git a/tests/functional/openlp_plugins/songs/test_ewimport.py b/tests/functional/openlp_plugins/songs/test_ewimport.py
index 1e84134bd..b58fcb249 100644
--- a/tests/functional/openlp_plugins/songs/test_ewimport.py
+++ b/tests/functional/openlp_plugins/songs/test_ewimport.py
@@ -153,10 +153,10 @@ class TestEasyWorshipSongImport(TestCase):
# THEN:
self.assertIsNotNone(field_desc_entry, 'Import should not be none')
- self.assertEquals(field_desc_entry.name, name, 'FieldDescEntry.name should be the same as the name argument')
- self.assertEquals(field_desc_entry.field_type, field_type,
+ self.assertEqual(field_desc_entry.name, name, 'FieldDescEntry.name should be the same as the name argument')
+ self.assertEqual(field_desc_entry.field_type, field_type,
'FieldDescEntry.type should be the same as the type argument')
- self.assertEquals(field_desc_entry.size, size, 'FieldDescEntry.size should be the same as the size argument')
+ self.assertEqual(field_desc_entry.size, size, 'FieldDescEntry.size should be the same as the size argument')
def create_importer_test(self):
"""
@@ -188,7 +188,7 @@ class TestEasyWorshipSongImport(TestCase):
for field_name in existing_fields:
# THEN: The item corresponding the index returned should have the same name attribute
- self.assertEquals(importer.field_descriptions[importer.find_field(field_name)].name, field_name)
+ self.assertEqual(importer.field_descriptions[importer.find_field(field_name)].name, field_name)
def find_non_existing_field_test(self):
"""
@@ -244,7 +244,7 @@ class TestEasyWorshipSongImport(TestCase):
return_value = importer.get_field(field_index)
# THEN: get_field should return the known results
- self.assertEquals(return_value, result,
+ self.assertEqual(return_value, result,
'get_field should return "%s" when called with "%s"' %
(result, TEST_FIELDS[field_index]))
@@ -271,7 +271,7 @@ class TestEasyWorshipSongImport(TestCase):
get_field_seek_calls = test_results[2]['seek']
# THEN: get_field should return the appropriate value with the appropriate mocked objects being called
- self.assertEquals(importer.get_field(field_index), get_field_result)
+ self.assertEqual(importer.get_field(field_index), get_field_result)
for call in get_field_read_calls:
mocked_memo_file.read.assert_any_call(call)
for call in get_field_seek_calls:
@@ -417,12 +417,12 @@ class TestEasyWorshipSongImport(TestCase):
if song_copyright:
self.assertEqual(importer.copyright, song_copyright)
if ccli_number:
- self.assertEquals(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s'
+ self.assertEqual(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s'
% (title, ccli_number))
for verse_text, verse_tag in add_verse_calls:
mocked_add_verse.assert_any_call(verse_text, verse_tag)
if verse_order_list:
- self.assertEquals(importer.verse_order_list, verse_order_list,
+ self.assertEqual(importer.verse_order_list, verse_order_list,
'verse_order_list for %s should be %s' % (title, verse_order_list))
mocked_finish.assert_called_with()
diff --git a/tests/functional/openlp_plugins/songs/test_lib.py b/tests/functional/openlp_plugins/songs/test_lib.py
index f6e5d98b9..2ab808bc9 100644
--- a/tests/functional/openlp_plugins/songs/test_lib.py
+++ b/tests/functional/openlp_plugins/songs/test_lib.py
@@ -96,10 +96,10 @@ class TestLib(TestCase):
self.song2.search_lyrics = self.full_lyrics
# WHEN: We compare those songs for equality.
- result = songs_probably_equal(self.song1, self.song2)
+ result = songs_probably_equal((self.song1, self.song2))
- # THEN: The result should be True.
- assert result is True, 'The result should be True'
+ # THEN: The result should be a tuple..
+ assert result == (self.song1, self.song2), 'The result should be the tuble of songs'
def songs_probably_equal_short_song_test(self):
"""
@@ -110,10 +110,10 @@ class TestLib(TestCase):
self.song2.search_lyrics = self.short_lyrics
# WHEN: We compare those songs for equality.
- result = songs_probably_equal(self.song1, self.song2)
+ result = songs_probably_equal((self.song1, self.song2))
- # THEN: The result should be True.
- assert result is True, 'The result should be True'
+ # THEN: The result should be a tuple..
+ assert result == (self.song1, self.song2), 'The result should be the tuble of songs'
def songs_probably_equal_error_song_test(self):
"""
@@ -124,10 +124,11 @@ class TestLib(TestCase):
self.song2.search_lyrics = self.error_lyrics
# WHEN: We compare those songs for equality.
- result = songs_probably_equal(self.song1, self.song2)
+ result = songs_probably_equal((self.song1, self.song2))
+
+ # THEN: The result should be a tuple of songs..
+ assert result == (self.song1, self.song2), 'The result should be the tuble of songs'
- # THEN: The result should be True.
- assert result is True, 'The result should be True'
def songs_probably_equal_different_song_test(self):
"""
@@ -138,10 +139,10 @@ class TestLib(TestCase):
self.song2.search_lyrics = self.different_lyrics
# WHEN: We compare those songs for equality.
- result = songs_probably_equal(self.song1, self.song2)
+ result = songs_probably_equal((self.song1, self.song2))
- # THEN: The result should be False.
- assert result is False, 'The result should be False'
+ # THEN: The result should be None.
+ assert result is None, 'The result should be None'
def remove_typos_beginning_test(self):
"""
diff --git a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py
index e7bd891d3..f08cedec5 100644
--- a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py
+++ b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py
@@ -35,6 +35,7 @@ from unittest import TestCase
from tests.functional import MagicMock, patch
from openlp.plugins.songs.lib.songbeamerimport import SongBeamerImport
+from openlp.plugins.songs.lib import VerseType
TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
'..', '..', '..', 'resources', 'songbeamersongs'))
@@ -89,7 +90,7 @@ class TestSongBeamerImport(TestCase):
# THEN: do_import should return none and the progress bar maximum should not be set.
self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is not a list')
- self.assertEquals(mocked_import_wizard.progress_bar.setMaximum.called, False,
+ self.assertEqual(mocked_import_wizard.progress_bar.setMaximum.called, False,
'setMaxium on import_wizard.progress_bar should not have been called')
def valid_import_source_test(self):
@@ -143,13 +144,90 @@ class TestSongBeamerImport(TestCase):
# THEN: do_import should return none, the song data should be as expected, and finish should have been
# called.
self.assertIsNone(importer.do_import(), 'do_import should return None when it has completed')
- self.assertEquals(importer.title, title, 'title for %s should be "%s"' % (song_file, title))
+ self.assertEqual(importer.title, title, 'title for %s should be "%s"' % (song_file, title))
for verse_text, verse_tag in add_verse_calls:
mocked_add_verse.assert_any_call(verse_text, verse_tag)
if song_book_name:
- self.assertEquals(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' %
+ self.assertEqual(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' %
(song_file, song_book_name))
if song_number:
- self.assertEquals(importer.song_number, song_number, 'song_number for %s should be %s' %
+ self.assertEqual(importer.song_number, song_number, 'song_number for %s should be %s' %
(song_file, song_number))
mocked_finish.assert_called_with()
+
+ def check_verse_marks_test(self):
+ """
+ Tests different lines to see if a verse mark is detected or not
+ """
+
+ # GIVEN: line with unnumbered verse-type
+ line = 'Refrain'
+ self.current_verse_type = None
+ # WHEN: line is being checked for verse marks
+ result = SongBeamerImport.check_verse_marks(self, line)
+ # THEN: we should get back true and c as self.current_verse_type
+ self.assertTrue(result, 'Versemark for should be found, value true')
+ self.assertEqual(self.current_verse_type, 'c', ' should be interpreted as ')
+
+ # GIVEN: line with unnumbered verse-type and trailing space
+ line = 'Refrain '
+ self.current_verse_type = None
+ # WHEN: line is being checked for verse marks
+ result = SongBeamerImport.check_verse_marks(self, line)
+ # THEN: we should get back true and c as self.current_verse_type
+ self.assertTrue(result, 'Versemark for should be found, value true')
+ self.assertEqual(self.current_verse_type, 'c', ' should be interpreted as ')
+
+ # GIVEN: line with numbered verse-type
+ line = 'Verse 1'
+ self.current_verse_type = None
+ # WHEN: line is being checked for verse marks
+ result = SongBeamerImport.check_verse_marks(self, line)
+ # THEN: we should get back true and v1 as self.current_verse_type
+ self.assertTrue(result, 'Versemark for should be found, value true')
+ self.assertEqual(self.current_verse_type, 'v1', u' should be interpreted as ')
+
+ # GIVEN: line with special unnumbered verse-mark (used in Songbeamer to allow usage of non-supported tags)
+ line = '$$M=special'
+ self.current_verse_type = None
+ # WHEN: line is being checked for verse marks
+ result = SongBeamerImport.check_verse_marks(self, line)
+ # THEN: we should get back true and o as self.current_verse_type
+ self.assertTrue(result, 'Versemark for <$$M=special> should be found, value true')
+ self.assertEqual(self.current_verse_type, 'o', u'<$$M=special> should be interpreted as ')
+
+ # GIVEN: line with song-text with 3 words
+ line = 'Jesus my saviour'
+ self.current_verse_type = None
+ # WHEN: line is being checked for verse marks
+ result = SongBeamerImport.check_verse_marks(self, line)
+ # THEN: we should get back false and none as self.current_verse_type
+ self.assertFalse(result, 'No versemark for should be found, value false')
+ self.assertIsNone(self.current_verse_type, ' should be interpreted as none versemark')
+
+ # GIVEN: line with song-text with 2 words
+ line = 'Praise him'
+ self.current_verse_type = None
+ # WHEN: line is being checked for verse marks
+ result = SongBeamerImport.check_verse_marks(self, line)
+ # THEN: we should get back false and none as self.current_verse_type
+ self.assertFalse(result, 'No versemark for should be found, value false')
+ self.assertIsNone(self.current_verse_type, ' should be interpreted as none versemark')
+
+ # GIVEN: line with only a space (could occur, nothing regular)
+ line = ' '
+ self.current_verse_type = None
+ # WHEN: line is being checked for verse marks
+ result = SongBeamerImport.check_verse_marks(self, line)
+ # THEN: we should get back false and none as self.current_verse_type
+ self.assertFalse(result, 'No versemark for < > should be found, value false')
+ self.assertIsNone(self.current_verse_type, '< > should be interpreted as none versemark')
+
+ # GIVEN: blank line (could occur, nothing regular)
+ line = ''
+ self.current_verse_type = None
+ # WHEN: line is being checked for verse marks
+ result = SongBeamerImport.check_verse_marks(self, line)
+ # THEN: we should get back false and none as self.current_verse_type
+ self.assertFalse(result, 'No versemark for <> should be found, value false')
+ self.assertIsNone(self.current_verse_type, '<> should be interpreted as none versemark')
diff --git a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py
index 7876558e9..f2839c332 100644
--- a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py
+++ b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py
@@ -95,7 +95,7 @@ class TestSongShowPlusImport(TestCase):
# THEN: do_import should return none and the progress bar maximum should not be set.
self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is not a list')
- self.assertEquals(mocked_import_wizard.progress_bar.setMaximum.called, False,
+ self.assertEqual(mocked_import_wizard.progress_bar.setMaximum.called, False,
'setMaximum on import_wizard.progress_bar should not have been called')
def valid_import_source_test(self):
@@ -143,7 +143,7 @@ class TestSongShowPlusImport(TestCase):
# THEN: The returned value should should correlate with the input arguments
for original_tag, openlp_tag in test_values:
- self.assertEquals(importer.to_openlp_verse_tag(original_tag), openlp_tag,
+ self.assertEqual(importer.to_openlp_verse_tag(original_tag), openlp_tag,
'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' %
(openlp_tag, original_tag))
@@ -172,6 +172,6 @@ class TestSongShowPlusImport(TestCase):
# THEN: The returned value should should correlate with the input arguments
for original_tag, openlp_tag in test_values:
- self.assertEquals(importer.to_openlp_verse_tag(original_tag, ignore_unique=True), openlp_tag,
+ self.assertEqual(importer.to_openlp_verse_tag(original_tag, ignore_unique=True), openlp_tag,
'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' %
(openlp_tag, original_tag))
diff --git a/tests/functional/openlp_plugins/songs/test_zionworximport.py b/tests/functional/openlp_plugins/songs/test_zionworximport.py
new file mode 100644
index 000000000..2edc071c7
--- /dev/null
+++ b/tests/functional/openlp_plugins/songs/test_zionworximport.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2014 Raoul Snyman #
+# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+"""
+This module contains tests for the ZionWorx song importer.
+"""
+
+from unittest import TestCase
+
+from tests.functional import MagicMock, patch
+from openlp.plugins.songs.lib.zionworximport import ZionWorxImport
+from openlp.plugins.songs.lib.songimport import SongImport
+
+
+class TestZionWorxImport(TestCase):
+ """
+ Test the functions in the :mod:`zionworximport` module.
+ """
+ def create_importer_test(self):
+ """
+ Test creating an instance of the ZionWorx file importer
+ """
+ # GIVEN: A mocked out SongImport class, and a mocked out "manager"
+ with patch('openlp.plugins.songs.lib.songbeamerimport.SongImport'):
+ mocked_manager = MagicMock()
+
+ # WHEN: An importer object is created
+ importer = ZionWorxImport(mocked_manager, filenames=[])
+
+ # THEN: The importer should be an instance of SongImport
+ self.assertIsInstance(importer, SongImport)
diff --git a/tests/helpers/songfileimport.py b/tests/helpers/songfileimport.py
index cc67770c1..49a09528c 100644
--- a/tests/helpers/songfileimport.py
+++ b/tests/helpers/songfileimport.py
@@ -110,29 +110,29 @@ class SongImportTestHelper(TestCase):
# THEN: do_import should return none, the song data should be as expected, and finish should have been
# called.
self.assertIsNone(importer.do_import(), 'do_import should return None when it has completed')
- self.assertEquals(importer.title, title, 'title for %s should be "%s"' % (source_file_name, title))
+ self.assertEqual(importer.title, title, 'title for %s should be "%s"' % (source_file_name, title))
for author in author_calls:
self.mocked_parse_author.assert_any_call(author)
if song_copyright:
self.mocked_add_copyright.assert_called_with(song_copyright)
if ccli_number:
- self.assertEquals(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s' %
+ self.assertEqual(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s' %
(source_file_name, ccli_number))
for verse_text, verse_tag in add_verse_calls:
self.mocked_add_verse.assert_any_call(verse_text, verse_tag)
if topics:
- self.assertEquals(importer.topics, topics, 'topics for %s should be %s' % (source_file_name, topics))
+ self.assertEqual(importer.topics, topics, 'topics for %s should be %s' % (source_file_name, topics))
if comments:
- self.assertEquals(importer.comments, comments, 'comments for %s should be "%s"' %
+ self.assertEqual(importer.comments, comments, 'comments for %s should be "%s"' %
(source_file_name, comments))
if song_book_name:
- self.assertEquals(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' %
+ self.assertEqual(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' %
(source_file_name, song_book_name))
if song_number:
- self.assertEquals(importer.song_number, song_number, 'song_number for %s should be %s' %
+ self.assertEqual(importer.song_number, song_number, 'song_number for %s should be %s' %
(source_file_name, song_number))
if verse_order_list:
- self.assertEquals(importer.verse_order_list, [], 'verse_order_list for %s should be %s' %
+ self.assertEqual(importer.verse_order_list, [], 'verse_order_list for %s should be %s' %
(source_file_name, verse_order_list))
self.mocked_finish.assert_called_with()
diff --git a/tests/interfaces/openlp_core_ui/test_servicemanager.py b/tests/interfaces/openlp_core_ui/test_servicemanager.py
index f4f5f26fc..78df788ab 100644
--- a/tests/interfaces/openlp_core_ui/test_servicemanager.py
+++ b/tests/interfaces/openlp_core_ui/test_servicemanager.py
@@ -313,6 +313,7 @@ class TestServiceManager(TestCase, TestMixin):
self.service_manager.notes_action.setVisible = MagicMock()
self.service_manager.time_action.setVisible = MagicMock()
self.service_manager.auto_start_action.setVisible = MagicMock()
+ self.service_manager.rename_action.setVisible = MagicMock()
# WHEN: Show the context menu.
self.service_manager.context_menu(q_point)
@@ -329,6 +330,8 @@ class TestServiceManager(TestCase, TestMixin):
'The action should be set invisible.'
self.service_manager.auto_start_action.setVisible.assert_called_with(True), \
'The action should be set visible.'
+ self.service_manager.rename_action.setVisible.assert_called_once_with(False), \
+ 'The action should be set invisible.'
def click_on_new_service_test(self):
"""
diff --git a/tests/interfaces/openlp_core_ui/test_splashscreen.py b/tests/interfaces/openlp_core_ui/test_splashscreen.py
new file mode 100644
index 000000000..35c15f9ec
--- /dev/null
+++ b/tests/interfaces/openlp_core_ui/test_splashscreen.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2014 Raoul Snyman #
+# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+"""
+Test the openlp.core.ui.splashscreen class.
+"""
+from unittest import TestCase
+
+from PyQt4 import QtGui
+
+from openlp.core.ui import SplashScreen
+from tests.helpers.testmixin import TestMixin
+
+
+class TestSplashScreen(TestCase, TestMixin):
+ def setUp(self):
+ self.get_application()
+ self.main_window = QtGui.QMainWindow()
+
+ def tearDown(self):
+ """
+ Delete all the C++ objects at the end so that we don't have a segfault
+ """
+ del self.app
+ del self.main_window
+
+ def setupUi_test(self):
+ """
+ Test if the setupUi method....
+ """
+ # GIVEN: A splash screen instance.
+ splash = SplashScreen()
+
+ # THEN: Check if the splash has a setupUi method.
+ assert hasattr(splash, 'setupUi'), 'The Splash Screen should have a setupUi() method.'
diff --git a/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py b/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py
index b085bd1df..84f80e7ed 100644
--- a/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py
+++ b/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py
@@ -83,7 +83,7 @@ class TestBibleManager(TestCase, TestMixin):
# WHEN asking to parse the bible reference
results = parse_reference('1 Timothy 1', self.manager.db_cache['tests'], MagicMock(), 54)
# THEN a verse array should be returned
- self.assertEquals([(54, 1, 1, -1)], results, "The bible verses should matches the expected results")
+ self.assertEqual([(54, 1, 1, -1)], results, "The bible verses should matches the expected results")
def parse_reference_two_test(self):
"""
@@ -93,7 +93,7 @@ class TestBibleManager(TestCase, TestMixin):
# WHEN asking to parse the bible reference
results = parse_reference('1 Timothy 1:1-2', self.manager.db_cache['tests'], MagicMock(), 54)
# THEN a verse array should be returned
- self.assertEquals([(54, 1, 1, 2)], results, "The bible verses should matches the expected results")
+ self.assertEqual([(54, 1, 1, 2)], results, "The bible verses should matches the expected results")
def parse_reference_three_test(self):
"""
@@ -103,5 +103,5 @@ class TestBibleManager(TestCase, TestMixin):
# WHEN asking to parse the bible reference
results = parse_reference('1 Timothy 1:1-2:1', self.manager.db_cache['tests'], MagicMock(), 54)
# THEN a verse array should be returned
- self.assertEquals([(54, 1, 1, -1), (54, 2, 1, 1)], results, "The bible verses should matches the expected "
+ self.assertEqual([(54, 1, 1, -1), (54, 2, 1, 1)], results, "The bible verses should matches the expected "
"results")
diff --git a/tests/resources/church2.jpg b/tests/resources/church2.jpg
new file mode 100644
index 000000000..826180870
Binary files /dev/null and b/tests/resources/church2.jpg differ
diff --git a/tests/resources/church3.jpg b/tests/resources/church3.jpg
new file mode 100644
index 000000000..826180870
Binary files /dev/null and b/tests/resources/church3.jpg differ
diff --git a/tests/resources/church4.jpg b/tests/resources/church4.jpg
new file mode 100644
index 000000000..826180870
Binary files /dev/null and b/tests/resources/church4.jpg differ
diff --git a/tests/resources/service/test.osz b/tests/resources/service/test.osz
new file mode 100644
index 000000000..a289c0775
Binary files /dev/null and b/tests/resources/service/test.osz differ
diff --git a/tests/utils/test_bzr_tags.py b/tests/utils/test_bzr_tags.py
new file mode 100644
index 000000000..95017e94f
--- /dev/null
+++ b/tests/utils/test_bzr_tags.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2014 Raoul Snyman #
+# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+"""
+Package to test for proper bzr tags.
+"""
+import os
+
+from unittest import TestCase
+
+from subprocess import Popen, PIPE
+
+TAGS = [
+ ['1.9.0', '1'],
+ ['1.9.1', '775'],
+ ['1.9.2', '890'],
+ ['1.9.3', '1063'],
+ ['1.9.4', '1196'],
+ ['1.9.5', '1421'],
+ ['1.9.6', '1657'],
+ ['1.9.7', '1761'],
+ ['1.9.8', '1856'],
+ ['1.9.9', '1917'],
+ ['1.9.10', '2003'],
+ ['1.9.11', '2039'],
+ ['1.9.12', '2063'],
+ ['2.0', '2118'],
+ ['2.0.1', '?'],
+ ['2.0.2', '?'],
+ ['2.0.3', '?'],
+ ['2.1.0', '2119']
+]
+
+
+class TestBzrTags(TestCase):
+
+ def bzr_tags_test(self):
+ """
+ Test for proper bzr tags
+ """
+ # GIVEN: A bzr branch
+ path = os.path.dirname(__file__)
+
+ # WHEN getting the branches tags
+ bzr = Popen(('bzr', 'tags', '--directory=' + path), stdout=PIPE)
+ stdout = bzr.communicate()[0]
+ tags = [line.decode('utf-8').split() for line in stdout.splitlines()]
+
+ # THEN the tags should match the accepted tags
+ self.assertEqual(TAGS, tags, 'List of tags should match')