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 888ca14c4..b1e254f82 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -108,8 +108,12 @@ 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 + ``IsOptical`` .Determines is the service_item is based on an optical device + """ CanPreview = 1 CanEdit = 2 @@ -127,7 +131,8 @@ class ItemCapabilities(object): CanWordSplit = 14 HasBackgroundAudio = 15 CanAutoStartForLive = 16 - IsOptical = 17 + CanEditTitle = 17 + IsOptical = 18 class ServiceItem(RegistryProperties): @@ -386,7 +391,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 @@ -429,7 +434,8 @@ class ServiceItem(RegistryProperties): """ Returns the title of the service item. """ - if self.is_text() or self.is_capable(ItemCapabilities.IsOptical): + if self.is_text() or self.is_capable(ItemCapabilities.IsOptical) \ + or self.is_capable(temCapabilities.CanEditTitle): 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 71d14b6a2..5174af63f 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 5f30f1096..c720c22d0 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) @@ -560,7 +560,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: @@ -571,7 +572,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 c2af902d4..74e6750d7 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -103,7 +103,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): """ @@ -164,7 +163,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): """ @@ -261,6 +260,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 cde0b1692..ca201279a 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -305,7 +305,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('') + + # 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 9e327517c..c1b9db52d 100644 --- a/tests/functional/openlp_plugins/songs/test_ewimport.py +++ b/tests/functional/openlp_plugins/songs/test_ewimport.py @@ -139,10 +139,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): """ @@ -174,7 +174,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): """ @@ -230,7 +230,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])) @@ -257,7 +257,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: @@ -403,11 +403,11 @@ 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')