def on_edit_book_button_clicked(self):
     """
     Edit a book.
     """
     book_id = self._get_current_item_id(self.song_books_list_widget)
     if book_id == -1:
         return
     book = self.manager.get_object(Book, book_id)
     if book.publisher is None:
         book.publisher = ''
     self.song_book_form.name_edit.setText(book.name)
     self.song_book_form.publisher_edit.setText(book.publisher)
     # Save the book's name and publisher for the case that they have to
     # be restored.
     temp_name = book.name
     temp_publisher = book.publisher
     if self.song_book_form.exec_(False):
         book.name = self.song_book_form.name_edit.text()
         book.publisher = self.song_book_form.publisher_edit.text()
         if self.check_song_book_exists(book, True):
             if self.manager.save_object(book):
                 self.reset_song_books()
             else:
                 critical_error_message_box(
                     message=translate('SongsPlugin.SongMaintenanceForm', 'Could not save your changes.'))
         elif critical_error_message_box(
             message=translate('SongsPlugin.SongMaintenanceForm',
                               'The book %s already exists. Would you like to make '
                               'songs with book %s use the existing book %s?') % (book.name, temp_name, book.name),
                 parent=self, question=True) == QtGui.QMessageBox.Yes:
             self._merge_objects(book, self.merge_song_books, self.reset_song_books)
         else:
             # We restore the book's old name and publisher.
             book.name = temp_name
             book.publisher = temp_publisher
示例#2
0
    def trigger_alert(self, text):
        """
        Prepares the alert text for displaying.

        :param text: The alert text.
        """
        if not text:
            return False
        # We found '<>' in the alert text, but the ParameterEdit field is empty.
        if text.find('<>') != -1 and not self.parameter_edit.text() and \
            QtGui.QMessageBox.question(self,
                                       translate('AlertsPlugin.AlertForm', 'No Parameter Found'),
                                       translate('AlertsPlugin.AlertForm',
                                                 'You have not entered a parameter to be replaced.\n'
                                                 'Do you want to continue anyway?'),
                                       QtGui.QMessageBox.StandardButtons(
                                           QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
            self.parameter_edit.setFocus()
            return False
        # The ParameterEdit field is not empty, but we have not found '<>'
        # in the alert text.
        elif text.find('<>') == -1 and self.parameter_edit.text() and \
            QtGui.QMessageBox.question(self,
                                       translate('AlertsPlugin.AlertForm', 'No Placeholder Found'),
                                       translate('AlertsPlugin.AlertForm', 'The alert text does not contain \'<>\'.\n'
                                                 'Do you want to continue anyway?'),
                                       QtGui.QMessageBox.StandardButtons(
                                           QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
            self.parameter_edit.setFocus()
            return False
        text = text.replace('<>', self.parameter_edit.text())
        self.plugin.alerts_manager.display_alert(text)
        return True
示例#3
0
    def validate_xml_file(self, filename, tag):
        """
        Validate the supplied file

        :param filename: The supplied file
        :param tag: The expected root tag type
        :return: True if valid. ValidationError is raised otherwise.
        """
        if BibleImport.is_compressed(filename):
            raise ValidationError(msg='Compressed file')
        bible = self.parse_xml(filename, use_objectify=True)
        if bible is None:
            raise ValidationError(msg='Error when opening file')
        root_tag = bible.tag.lower()
        bible_type = translate('BiblesPlugin.BibleImport', 'unknown type of',
                               'This looks like an unknown type of XML bible.')
        if root_tag == tag:
            return True
        elif root_tag == 'bible':
            bible_type = "OpenSong"
        elif root_tag == '{http://www.bibletechnologies.net/2003/osis/namespace}osis':
            bible_type = 'OSIS'
        elif root_tag == 'xmlbible':
            bible_type = 'Zefania'
        critical_error_message_box(
            message=translate('BiblesPlugin.BibleImport',
                              'Incorrect Bible file type supplied. This looks like an {bible_type} XML bible.'
                              .format(bible_type=bible_type)))
        raise ValidationError(msg='Invalid xml.')
示例#4
0
 def on_rename_theme(self, field=None):
     """
     Renames an existing theme to a new name
     :param field:
     """
     # TODO: Check for delayed format() conversions
     if self._validate_theme_action(translate('OpenLP.ThemeManager', 'You must select a theme to rename.'),
                                    translate('OpenLP.ThemeManager', 'Rename Confirmation'),
                                    translate('OpenLP.ThemeManager', 'Rename %s theme?'), False, False):
         item = self.theme_list_widget.currentItem()
         old_theme_name = item.data(QtCore.Qt.UserRole)
         self.file_rename_form.file_name_edit.setText(old_theme_name)
         if self.file_rename_form.exec():
             new_theme_name = self.file_rename_form.file_name_edit.text()
             if old_theme_name == new_theme_name:
                 return
             if self.check_if_theme_exists(new_theme_name):
                 old_theme_data = self.get_theme_data(old_theme_name)
                 self.clone_theme_data(old_theme_data, new_theme_name)
                 self.delete_theme(old_theme_name)
                 for plugin in self.plugin_manager.plugins:
                     if plugin.uses_theme(old_theme_name):
                         plugin.rename_theme(old_theme_name, new_theme_name)
                 self.renderer.update_theme(new_theme_name, old_theme_name)
                 self.load_themes()
示例#5
0
 def post_wizard(self):
     """
     Clean up the UI after the import has finished.
     """
     successful_import = 0
     failed_import = 0
     for number, filename in enumerate(self.files):
         if self.success.get(number):
             successful_import += 1
         elif self.checkBox[number].checkState() == QtCore.Qt.Checked:
             failed_import += 1
             # Delete upgraded (but not complete, corrupted, ...) bible.
             delete_file(os.path.join(self.path, filename[0]))
             # Copy not upgraded bible back.
             shutil.move(os.path.join(self.temp_dir, filename[0]), self.path)
     if failed_import > 0:
         failed_import_text = translate('BiblesPlugin.UpgradeWizardForm', ', %s failed') % failed_import
     else:
         failed_import_text = ''
     if successful_import > 0:
         if self.includeWebBible:
             self.progress_label.setText(
                 translate('BiblesPlugin.UpgradeWizardForm',
                           'Upgrading Bible(s): %s successful%s\nPlease note that verses from Web Bibles will be '
                           'downloaded on demand and so an Internet connection is required.') %
                 (successful_import, failed_import_text))
         else:
             self.progress_label.setText(
                 translate('BiblesPlugin.UpgradeWizardForm', 'Upgrading Bible(s): %s successful%s') % (
                     successful_import, failed_import_text))
     else:
         self.progress_label.setText(translate('BiblesPlugin.UpgradeWizardForm', 'Upgrade failed.'))
     # Remove temp directory.
     shutil.rmtree(self.temp_dir, True)
     super(BibleUpgradeForm, self).post_wizard()
示例#6
0
    def media_length(self, service_item):
        """
        Loads and starts a media item to obtain the media length

        :param service_item: The ServiceItem containing the details to be played.
        """
        controller = self.display_controllers[DisplayControllerType.Plugin]
        log.debug('media_length')
        # stop running videos
        self.media_reset(controller)
        controller.media_info = MediaInfo()
        controller.media_info.volume = 0
        controller.media_info.file_info = QtCore.QFileInfo(service_item.get_frame_path())
        display = controller.preview_display
        if not self._check_file_type(controller, display, service_item):
            # Media could not be loaded correctly
            critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'),
                                       translate('MediaPlugin.MediaItem', 'Unsupported File'))
            return False
        if not self.media_play(controller):
            critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'),
                                       translate('MediaPlugin.MediaItem', 'Unsupported File'))
            return False
        service_item.set_media_length(controller.media_info.length)
        self.media_stop(controller)
        log.debug('use %s controller' % self.current_media_players[controller.controller_type])
        return True
示例#7
0
def create_separated_list(string_list):
    """
    Returns a string that represents a join of a list of strings with a localized separator. This function corresponds

    to QLocale::createSeparatedList which was introduced in Qt 4.8 and implements the algorithm from
    http://www.unicode.org/reports/tr35/#ListPatterns

     :param string_list: List of unicode strings
    """
    if LooseVersion(Qt.PYQT_VERSION_STR) >= LooseVersion('4.9') and LooseVersion(Qt.qVersion()) >= LooseVersion('4.8'):
        return QtCore.QLocale().createSeparatedList(string_list)
    if not string_list:
        return ''
    elif len(string_list) == 1:
        return string_list[0]
    elif len(string_list) == 2:
        return translate('OpenLP.core.lib', '%s and %s',
                         'Locale list separator: 2 items') % (string_list[0], string_list[1])
    else:
        merged = translate('OpenLP.core.lib', '%s, and %s',
                           'Locale list separator: end') % (string_list[-2], string_list[-1])
        for index in reversed(list(range(1, len(string_list) - 2))):
            merged = translate('OpenLP.core.lib', '%s, %s',
                               'Locale list separator: middle') % (string_list[index], merged)
        return translate('OpenLP.core.lib', '%s, %s', 'Locale list separator: start') % (string_list[0], merged)
示例#8
0
 def on_text_search(self, text, search_while_type=False):
     """
     We are doing a 'Text Search'.
     This search is called on def text_search by 'Search' Text and Combined Searches.
     """
     self.search_results = self.plugin.manager.verse_search(self.bible.name, text)
     if self.second_bible and self.search_results:
         filtered_search_results = []
         not_found_count = 0
         for verse in self.search_results:
             second_verse = self.second_bible.get_verses(
                 [(verse.book.book_reference_id, verse.chapter, verse.verse, verse.verse)], False)
             if second_verse:
                 filtered_search_results.append(verse)
                 self.second_search_results += second_verse
             else:
                 log.debug('Verse "{name} {chapter:d}:{verse:d}" not found in Second Bible "{bible_name}"'.format(
                     name=verse.book.name, chapter=verse.chapter,
                     verse=verse.verse, bible_name=self.second_bible.name))
                 not_found_count += 1
         self.search_results = filtered_search_results
         if not_found_count != 0 and not search_while_type:
             self.main_window.information_message(
                 translate('BiblesPlugin.MediaItem', 'Verses not found'),
                 translate('BiblesPlugin.MediaItem',
                           'The second Bible "{second_name}" does not contain all the verses that are in the main '
                           'Bible "{name}".\nOnly verses found in both Bibles will be shown.\n\n'
                           '{count:d} verses have not been included in the results.'
                           ).format(second_name=self.second_bible.name, name=self.bible.name, count=not_found_count))
     self.display_results()
示例#9
0
    def set_language(action, message=True):
        """
        Set the language to translate OpenLP into

        :param action:  The language menu option
        :param message:  Display the message option
        """
        language = "en"
        if action:
            action_name = str(action.objectName())
            if action_name == "autoLanguageItem":
                LanguageManager.auto_language = True
            else:
                LanguageManager.auto_language = False
                qm_list = LanguageManager.get_qm_list()
                language = str(qm_list[action_name])
        if LanguageManager.auto_language:
            language = "[%s]" % language
        Settings().setValue("core/language", language)
        log.info("Language file: '%s' written to conf file" % language)
        if message:
            QtGui.QMessageBox.information(
                None,
                translate("OpenLP.LanguageManager", "Language"),
                translate("OpenLP.LanguageManager", "Please restart OpenLP to use your new " "language setting."),
            )
示例#10
0
    def __init__(self, parent, projectordb, edit=False):
        """
        Build the source select dialog using tabbed interface.

        :param projectordb: ProjectorDB session to use
        """
        log.debug('Initializing SourceSelectTabs()')
        super(SourceSelectTabs, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
        self.setMinimumWidth(350)
        self.projectordb = projectordb
        self.edit = edit
        if self.edit:
            title = translate('OpenLP.SourceSelectForm', 'Edit Projector Source Text')
        else:
            title = translate('OpenLP.SourceSelectForm', 'Select Projector Source')
        self.setWindowTitle(title)
        self.setObjectName('source_select_tabs')
        self.setWindowIcon(build_icon(':/icon/openlp-log.svg'))
        self.setModal(True)
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.setObjectName('source_select_tabs_layout')
        if is_macosx():
            self.tabwidget = QtWidgets.QTabWidget(self)
        else:
            self.tabwidget = FingerTabWidget(self)
        self.tabwidget.setObjectName('source_select_tabs_tabwidget')
        self.tabwidget.setUsesScrollButtons(False)
        if is_macosx():
            self.tabwidget.setTabPosition(QtWidgets.QTabWidget.North)
        else:
            self.tabwidget.setTabPosition(QtWidgets.QTabWidget.West)
        self.layout.addWidget(self.tabwidget)
        self.setLayout(self.layout)
示例#11
0
 def text_search(self, search_while_type=False):
     """
     This triggers the proper 'Search' search based on which search type is used.
     "Eg. "Reference Search", "Text Search" or "Combined search".
     """
     log.debug('text_search called')
     text = self.search_edit.text()
     if text == '':
         self.list_view.clear()
         return
     self.list_view.clear(search_while_typing=search_while_type)
     if self.search_edit.current_search_type() == BibleSearch.Reference:
         if get_reference_match('full').match(text):
             # Valid reference found. Do reference search.
             self.text_reference_search(text)
         elif not search_while_type:
             self.main_window.information_message(
                 translate('BiblesPlugin.BibleManager', 'Scripture Reference Error'),
                 translate('BiblesPlugin.BibleManager',
                           '<strong>The reference you typed is invalid!<br><br>'
                           'Please make sure that your reference follows one of these patterns:</strong><br><br>%s')
                 % UiStrings().BibleScriptureError % get_reference_separators())
     elif self.search_edit.current_search_type() == BibleSearch.Combined and get_reference_match('full').match(text):
             # Valid reference found. Do reference search.
             self.text_reference_search(text)
     else:
         # It can only be a 'Combined' search without a valid reference, or a 'Text' search
         if search_while_type:
             if len(text) > 8 and VALID_TEXT_SEARCH.search(text):
                 self.on_text_search(text, True)
         elif VALID_TEXT_SEARCH.search(text):
             self.on_text_search(text)
示例#12
0
 def set_plugin_text_strings(self):
     """
     Called to define all translatable texts of the plugin
     """
     # Name PluginList
     self.text_strings[StringContent.Name] = {
         'singular': translate('MediaPlugin', 'Media', 'name singular'),
         'plural': translate('MediaPlugin', 'Media', 'name plural')
     }
     # Name for MediaDockManager, SettingsManager
     self.text_strings[StringContent.VisibleName] = {
         'title': translate('MediaPlugin', 'Media', 'container title')
     }
     # Middle Header Bar
     tooltips = {
         'load': translate('MediaPlugin', 'Load new media.'),
         'import': '',
         'new': translate('MediaPlugin', 'Add new media.'),
         'edit': translate('MediaPlugin', 'Edit the selected media.'),
         'delete': translate('MediaPlugin', 'Delete the selected media.'),
         'preview': translate('MediaPlugin', 'Preview the selected media.'),
         'live': translate('MediaPlugin', 'Send the selected media live.'),
         'service': translate('MediaPlugin', 'Add the selected media to the service.')
     }
     self.set_plugin_ui_text_strings(tooltips)
示例#13
0
 def on_replace_click(self):
     """
     Called to replace Live background with the media selected.
     """
     if check_item_selected(self.list_view,
                            translate('MediaPlugin.MediaItem',
                                      'You must select a media file to replace the background with.')):
         item = self.list_view.currentItem()
         filename = item.data(QtCore.Qt.UserRole)
         if os.path.exists(filename):
             service_item = ServiceItem()
             service_item.title = 'webkit'
             service_item.processor = 'webkit'
             (path, name) = os.path.split(filename)
             service_item.add_from_command(path, name, CLAPPERBOARD)
             if self.media_controller.video(DisplayControllerType.Live, service_item, video_behind_text=True):
                 self.reset_action.setVisible(True)
             else:
                 critical_error_message_box(UiStrings().LiveBGError,
                                            translate('MediaPlugin.MediaItem',
                                                      'There was no display item to amend.'))
         else:
             critical_error_message_box(UiStrings().LiveBGError,
                                        translate('MediaPlugin.MediaItem',
                                                  'There was a problem replacing your background, '
                                                  'the media file "%s" no longer exists.') % filename)
示例#14
0
 def accept(self):
     """
     Lets save the theme as Finish has been triggered
     """
     # Save the theme name
     self.theme.theme_name = self.field('name')
     if not self.theme.theme_name:
         critical_error_message_box(
             translate('OpenLP.ThemeWizard', 'Theme Name Missing'),
             translate('OpenLP.ThemeWizard', 'There is no name for this theme. Please enter one.'))
         return
     if self.theme.theme_name == '-1' or self.theme.theme_name == 'None':
         critical_error_message_box(
             translate('OpenLP.ThemeWizard', 'Theme Name Invalid'),
             translate('OpenLP.ThemeWizard', 'Invalid theme name. Please enter one.'))
         return
     save_from = None
     save_to = None
     if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or \
        self.theme.background_type == BackgroundType.to_string(BackgroundType.Video):
         filename = os.path.split(str(self.theme.background_filename))[1]
         save_to = os.path.join(self.path, self.theme.theme_name, filename)
         save_from = self.theme.background_filename
     if not self.edit_mode and not self.theme_manager.check_if_theme_exists(self.theme.theme_name):
         return
     self.theme_manager.save_theme(self.theme, save_from, save_to)
     return QtWidgets.QDialog.accept(self)
示例#15
0
 def validate_book(self, new_book_name, abbreviation):
     """
     Validate a book.
     """
     book_regex = re.compile('[\d]*[^\d]+$')
     if not new_book_name:
         self.book_name_edit[abbreviation].setFocus()
         critical_error_message_box(
             UiStrings().EmptyField,
             translate('BiblesPlugin.BibleEditForm', 'You need to specify a book name for "%s".') %
             self.book_names[abbreviation])
         return False
     elif not book_regex.match(new_book_name):
         self.book_name_edit[abbreviation].setFocus()
         critical_error_message_box(
             UiStrings().EmptyField,
             translate('BiblesPlugin.BibleEditForm',
                       'The book name "%s" is not correct.\nNumbers can only be used at the beginning and must\nbe '
                       'followed by one or more non-numeric characters.') % new_book_name)
         return False
     for abbr, book in self.books.items():
         if book:
             if abbr == abbreviation:
                 continue
             if self.book_name_edit[abbr].text() == new_book_name:
                 self.book_name_edit[abbreviation].setFocus()
                 critical_error_message_box(
                     translate('BiblesPlugin.BibleEditForm', 'Duplicate Book Name'),
                     translate('BiblesPlugin.BibleEditForm', 'The Book Name "%s" has been entered more than once.')
                     % new_book_name)
                 return False
     return True
示例#16
0
 def validate_meta(self, name, copyright):
     """
     Validate the Meta before saving.
     """
     if not name:
         self.version_name_edit.setFocus()
         critical_error_message_box(
             UiStrings().EmptyField,
             translate('BiblesPlugin.BibleEditForm', 'You need to specify a version name for your Bible.'))
         return False
     elif not copyright:
         self.copyright_edit.setFocus()
         critical_error_message_box(
             UiStrings().EmptyField,
             translate('BiblesPlugin.BibleEditForm',
                       'You need to set a copyright for your Bible. Bibles in the Public Domain need to be marked '
                       'as such.'))
         return False
     elif self.manager.exists(name) and self.manager.get_meta_data(self.bible, 'name').value != name:
         self.version_name_edit.setFocus()
         critical_error_message_box(
             translate('BiblesPlugin.BibleEditForm', 'Bible Exists'),
             translate('BiblesPlugin.BibleEditForm', 'This Bible already exists. Please import '
                       'a different Bible or first delete the existing one.'))
         return False
     return True
示例#17
0
 def retranslateUi(self):
     """
     The name of the plugin media displayed in UI
     """
     self.on_new_prompt = translate('PresentationPlugin.MediaItem', 'Select Presentation(s)')
     self.automatic = translate('PresentationPlugin.MediaItem', 'Automatic')
     self.display_type_label.setText(translate('PresentationPlugin.MediaItem', 'Present using:'))
示例#18
0
    def on_delete_loop(self, field=None):
        """
        Delete a loop triggered by the UI.
        :param field:
        """
        if check_item_selected(self.loop_list_widget,
                               translate('OpenLP.LoopManager', 'You must select a loop to delete.')):
            item = self.loop_list_widget.currentItem()
            cur_loop = item.text()
            check_answer = QtGui.QMessageBox.question(self, translate('OpenLP.LoopManager', 'Delete Confirmation'),
                                                      translate('OpenLP.LoopManager', 'Remove %s loop and delete files?' % cur_loop),
                                                      QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
                                                      QtGui.QMessageBox.No)
            if check_answer == QtGui.QMessageBox.No:
                return

            # Remove loop from UI
            row = self.loop_list_widget.row(item)
            self.loop_list_widget.takeItem(row)

            # Remove loop and thumbnail from disk
            self.application.set_busy_cursor()
            os.remove(os.path.join(self.path, item.data(QtCore.Qt.UserRole)))
            os.remove(os.path.join(self.thumb_path, cur_loop + '.jpg'))
            self.application.set_normal_cursor()
示例#19
0
 def retranslateUi(self, custom_slide_edit_dialog):
     custom_slide_edit_dialog.setWindowTitle(translate('CustomPlugin.EditVerseForm', 'Edit Slide'))
     self.split_button.setText(UiStrings().Split)
     self.split_button.setToolTip(UiStrings().SplitToolTip)
     self.insert_button.setText(translate('CustomPlugin.EditCustomForm', 'Insert Slide'))
     self.insert_button.setToolTip(translate('CustomPlugin.EditCustomForm',
                                             'Split a slide into two by inserting a slide splitter.'))
示例#20
0
 def on_add_group_click(self):
     """
     Called to add a new group
     """
     # Find out if a group must be pre-selected
     preselect_group = 0
     selected_items = self.list_view.selectedItems()
     if selected_items:
         selected_item = selected_items[0]
         if isinstance(selected_item.data(0, QtCore.Qt.UserRole), ImageFilenames):
             selected_item = selected_item.parent()
         if isinstance(selected_item, QtGui.QTreeWidgetItem):
             if isinstance(selected_item.data(0, QtCore.Qt.UserRole), ImageGroups):
                 preselect_group = selected_item.data(0, QtCore.Qt.UserRole).id
     # Show 'add group' dialog
     if self.add_group_form.exec_(show_top_level_group=True, selected_group=preselect_group):
         new_group = ImageGroups.populate(parent_id=self.add_group_form.parent_group_combobox.itemData(
             self.add_group_form.parent_group_combobox.currentIndex(), QtCore.Qt.UserRole),
             group_name=self.add_group_form.name_edit.text())
         if not self.check_group_exists(new_group):
             if self.manager.save_object(new_group):
                 self.load_full_list(self.manager.get_all_objects(
                     ImageFilenames, order_by_ref=ImageFilenames.filename))
                 self.expand_group(new_group.id)
                 self.fill_groups_combobox(self.choose_group_form.group_combobox)
                 self.fill_groups_combobox(self.add_group_form.parent_group_combobox)
             else:
                 critical_error_message_box(
                     message=translate('ImagePlugin.AddGroupForm', 'Could not add the new group.'))
         else:
             critical_error_message_box(message=translate('ImagePlugin.AddGroupForm', 'This group already exists.'))
示例#21
0
 def load(self):
     """
     Load the plugin details into the screen
     """
     self.plugin_list_widget.clear()
     self.programatic_change = True
     self._clear_details()
     self.programatic_change = True
     plugin_list_width = 0
     for plugin in self.plugin_manager.plugins:
         item = QtGui.QListWidgetItem(self.plugin_list_widget)
         # We do this just to make 100% sure the status is an integer as
         # sometimes when it's loaded from the config, it isn't cast to int.
         plugin.status = int(plugin.status)
         # Set the little status text in brackets next to the plugin name.
         if plugin.status == PluginStatus.Disabled:
             status_text = translate('OpenLP.PluginForm', '%s (Disabled)')
         elif plugin.status == PluginStatus.Active:
             status_text = translate('OpenLP.PluginForm', '%s (Active)')
         else:
             # PluginStatus.Inactive
             status_text = translate('OpenLP.PluginForm', '%s (Inactive)')
         item.setText(status_text % plugin.name_strings['singular'])
         # If the plugin has an icon, set it!
         if plugin.icon:
             item.setIcon(plugin.icon)
         self.plugin_list_widget.addItem(item)
         plugin_list_width = max(plugin_list_width, self.fontMetrics().width(
             translate('OpenLP.PluginForm', '%s (Inactive)') % plugin.name_strings['singular']))
     self.plugin_list_widget.setFixedWidth(plugin_list_width + self.plugin_list_widget.iconSize().width() + 48)
示例#22
0
 def _export_theme(self, path, theme):
     """
     Create the zipfile with the theme contents.
     :param path: Location where the zip file will be placed
     :param theme: The name of the theme to be exported
     """
     theme_path = os.path.join(path, theme + '.otz')
     theme_zip = None
     try:
         theme_zip = zipfile.ZipFile(theme_path, 'w')
         source = os.path.join(self.path, theme)
         for files in os.walk(source):
             for name in files[2]:
                 theme_zip.write(os.path.join(source, name), os.path.join(theme, name))
         theme_zip.close()
         return True
     except OSError as ose:
         self.log_exception('Export Theme Failed')
         critical_error_message_box(translate('OpenLP.ThemeManager', 'Theme Export Failed'),
                                    translate('OpenLP.ThemeManager', 'The theme export failed because this error '
                                                                     'occurred: {err}').format(err=ose.strerror))
         if theme_zip:
             theme_zip.close()
             shutil.rmtree(theme_path, True)
         return False
示例#23
0
 def on_data_directory_browse_button_clicked(self):
     """
     Browse for a new data directory location.
     """
     old_root_path = str(self.data_directory_label.text())
     # Get the new directory location.
     new_data_path = QtWidgets.QFileDialog.getExistingDirectory(self, translate('OpenLP.AdvancedTab',
                                                                                'Select Data Directory Location'),
                                                                old_root_path,
                                                                options=QtWidgets.QFileDialog.ShowDirsOnly)
     # Set the new data path.
     if new_data_path:
         new_data_path = os.path.normpath(new_data_path)
         if self.current_data_path.lower() == new_data_path.lower():
             self.on_data_directory_cancel_button_clicked()
             return
     else:
         return
     # Make sure they want to change the data.
     answer = QtWidgets.QMessageBox.question(self, translate('OpenLP.AdvancedTab', 'Confirm Data Directory Change'),
                                             translate('OpenLP.AdvancedTab', 'Are you sure you want to change the '
                                                       'location of the OpenLP data directory to:\n\n{path}'
                                                       '\n\nThe data directory will be changed when OpenLP is '
                                                       'closed.').format(path=new_data_path),
                                             QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
                                                                                   QtWidgets.QMessageBox.No),
                                             QtWidgets.QMessageBox.No)
     if answer != QtWidgets.QMessageBox.Yes:
         return
     # Check if data already exists here.
     self.check_data_overwrite(new_data_path)
     # Save the new location.
     self.main_window.set_new_data_path(new_data_path)
     self.new_data_directory_edit.setText(new_data_path)
     self.data_directory_cancel_button.show()
示例#24
0
 def first_time(self):
     """
     If the first time wizard has run, this function is run to import all the new songs into the database.
     """
     self.application.process_events()
     self.on_tools_reindex_item_triggered()
     self.application.process_events()
     db_dir = os.path.join(gettempdir(), 'openlp')
     if not os.path.exists(db_dir):
         return
     song_dbs = []
     song_count = 0
     for sfile in os.listdir(db_dir):
         if sfile.startswith('songs_') and sfile.endswith('.sqlite'):
             self.application.process_events()
             song_dbs.append(os.path.join(db_dir, sfile))
             song_count += SongsPlugin._count_songs(os.path.join(db_dir, sfile))
     if not song_dbs:
         return
     self.application.process_events()
     progress = QtWidgets.QProgressDialog(self.main_window)
     progress.setWindowModality(QtCore.Qt.WindowModal)
     progress.setWindowTitle(translate('OpenLP.Ui', 'Importing Songs'))
     progress.setLabelText(translate('OpenLP.Ui', 'Starting import...'))
     progress.setCancelButton(None)
     progress.setRange(0, song_count)
     progress.setMinimumDuration(0)
     progress.forceShow()
     self.application.process_events()
     for db in song_dbs:
         importer = OpenLPSongImport(self.manager, filename=db)
         importer.do_import(progress)
         self.application.process_events()
     progress.setValue(song_count)
     self.media_item.on_search_text_button_clicked()
示例#25
0
 def validateCurrentPage(self):
     """
     Validate the current page before moving on to the next page.
     """
     if self.currentPage() == self.welcome_page:
         return True
     elif self.currentPage() == self.available_songs_page:
         items = [
             item for item in self._find_list_widget_items(self.available_list_widget) if item.checkState()
         ]
         if not items:
             critical_error_message_box(
                 UiStrings().NISp,
                 translate('SongsPlugin.ExportWizardForm', 'You need to add at least one Song to export.'))
             return False
         self.selected_list_widget.clear()
         # Add the songs to the list of selected songs.
         for item in items:
             song = QtGui.QListWidgetItem(item.text())
             song.setData(QtCore.Qt.UserRole, item.data(QtCore.Qt.UserRole))
             song.setFlags(QtCore.Qt.ItemIsEnabled)
             self.selected_list_widget.addItem(song)
         return True
     elif self.currentPage() == self.export_song_page:
         if not self.directory_line_edit.text():
             critical_error_message_box(
                 translate('SongsPlugin.ExportWizardForm', 'No Save Location specified'),
                 translate('SongsPlugin.ExportWizardForm', 'You need to specify a directory.'))
             return False
         return True
     elif self.currentPage() == self.progress_page:
         self.available_list_widget.clear()
         self.selected_list_widget.clear()
         return True
示例#26
0
 def on_data_directory_default_button_clicked(self):
     """
     Re-set the data directory location to the 'default' location.
     """
     new_data_path = AppLocation.get_directory(AppLocation.DataDir)
     if self.current_data_path.lower() != new_data_path.lower():
         # Make sure they want to change the data location back to the
         # default.
         answer = QtWidgets.QMessageBox.question(self, translate('OpenLP.AdvancedTab', 'Reset Data Directory'),
                                                 translate('OpenLP.AdvancedTab', 'Are you sure you want to change '
                                                                                 'the location of the OpenLP data '
                                                                                 'directory to the default location?'
                                                                                 '\n\nThis location will be used '
                                                                                 'after OpenLP is closed.'),
                                                 QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
                                                                                       QtWidgets.QMessageBox.No),
                                                 QtWidgets.QMessageBox.No)
         if answer != QtWidgets.QMessageBox.Yes:
             return
         self.check_data_overwrite(new_data_path)
         # Save the new location.
         self.main_window.set_new_data_path(new_data_path)
         self.new_data_directory_edit.setText(os.path.abspath(new_data_path))
         self.data_directory_cancel_button.show()
     else:
         # We cancel the change in case user changed their mind.
         self.on_data_directory_cancel_button_clicked()
示例#27
0
 def on_replace_click(self):
     """
     Called to replace Live background with the image selected.
     """
     if check_item_selected(
             self.list_view,
             translate('ImagePlugin.MediaItem', 'You must select an image to replace the background with.')):
         background = QtGui.QColor(Settings().value(self.settings_section + '/background color'))
         bitem = self.list_view.selectedItems()[0]
         if not isinstance(bitem.data(0, QtCore.Qt.UserRole), ImageFilenames):
             # Only continue when an image is selected.
             return
         filename = bitem.data(0, QtCore.Qt.UserRole).filename
         if os.path.exists(filename):
             if self.live_controller.display.direct_image(filename, background):
                 self.reset_action.setVisible(True)
             else:
                 critical_error_message_box(
                     UiStrings().LiveBGError,
                     translate('ImagePlugin.MediaItem', 'There was no display item to amend.'))
         else:
             critical_error_message_box(
                 UiStrings().LiveBGError,
                 translate('ImagePlugin.MediaItem', 'There was a problem replacing your background, '
                           'the image file "%s" no longer exists.') % filename)
示例#28
0
 def on_edit_topic_button_clicked(self):
     """
     Edit a topic.
     """
     topic_id = self._get_current_item_id(self.topics_list_widget)
     if topic_id == -1:
         return
     topic = self.manager.get_object(Topic, topic_id)
     self.topic_form.name = topic.name
     # Save the topic's name for the case that he has to be restored.
     temp_name = topic.name
     if self.topic_form.exec_(False):
         topic.name = self.topic_form.name_edit.text()
         if self.check_topic_exists(topic, True):
             if self.manager.save_object(topic):
                 self.reset_topics()
             else:
                 critical_error_message_box(
                     message=translate('SongsPlugin.SongMaintenanceForm', 'Could not save your changes.'))
         elif critical_error_message_box(
             message=translate('SongsPlugin.SongMaintenanceForm',
                               'The topic %s already exists. Would you like to make songs with topic %s use the '
                               'existing topic %s?') % (topic.name, temp_name, topic.name),
                 parent=self, question=True) == QtGui.QMessageBox.Yes:
             self._merge_objects(topic, self.merge_topics, self.reset_topics)
         else:
             # We restore the topics's old name.
             topic.name = temp_name
             critical_error_message_box(
                 message=translate('SongsPlugin.SongMaintenanceForm',
                                   'Could not save your modified topic, because it already exists.'))
示例#29
0
    def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False,
                            context=ServiceItemContext.Service):
        """
        Generate the slide data. Needs to be implemented by the plugin.

        :param service_item: The service item to be built on
        :param item: The Song item to be used
        :param xml_version: The xml version (not used)
        :param remote: Triggered from remote
        :param context: Why is it being generated
        """
        if item is None:
            item = self.list_view.currentItem()
            if item is None:
                return False
        filename = item.data(QtCore.Qt.UserRole)
        # Special handling if the filename is a optical clip
        if filename.startswith('optical:'):
            (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(filename)
            if not os.path.exists(name):
                if not remote:
                    # Optical disc is no longer present
                    critical_error_message_box(
                        translate('MediaPlugin.MediaItem', 'Missing Media File'),
                        translate('MediaPlugin.MediaItem', 'The optical disc %s is no longer available.') % name)
                return False
            service_item.processor = self.display_type_combo_box.currentText()
            service_item.add_from_command(filename, name, CLAPPERBOARD)
            service_item.title = clip_name
            # Set the length
            self.media_controller.media_setup_optical(name, title, audio_track, subtitle_track, start, end, None, None)
            service_item.set_media_length((end - start) / 1000)
            service_item.start_time = start / 1000
            service_item.end_time = end / 1000
            service_item.add_capability(ItemCapabilities.IsOptical)
        else:
            if not os.path.exists(filename):
                if not remote:
                    # File is no longer present
                    critical_error_message_box(
                        translate('MediaPlugin.MediaItem', 'Missing Media File'),
                        translate('MediaPlugin.MediaItem', 'The file %s no longer exists.') % filename)
                return False
            (path, name) = os.path.split(filename)
            service_item.title = name
            service_item.processor = self.display_type_combo_box.currentText()
            service_item.add_from_command(path, name, CLAPPERBOARD)
            # Only get start and end times if going to a service
            if context == ServiceItemContext.Service:
                # Start media and obtain the length
                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
            # force a non-existent theme
        service_item.theme = -1
        return True
示例#30
0
 def check_data_overwrite(self, data_path):
     """
     Check if there's already data in the target directory.
     """
     test_path = os.path.join(data_path, 'songs')
     self.data_directory_copy_check_box.show()
     if os.path.exists(test_path):
         self.data_exists = True
         # Check is they want to replace existing data.
         answer = QtWidgets.QMessageBox.warning(self,
                                                translate('OpenLP.AdvancedTab', 'Overwrite Existing Data'),
                                                translate('OpenLP.AdvancedTab',
                                                          'WARNING: \n\nThe location you have selected \n\n{path}'
                                                          '\n\nappears to contain OpenLP data files. Do you wish to '
                                                          'replace these files with the current data '
                                                          'files?').format(path=os.path.abspath(data_path,)),
                                                QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
                                                                                      QtWidgets.QMessageBox.No),
                                                QtWidgets.QMessageBox.No)
         if answer == QtWidgets.QMessageBox.Yes:
             self.data_directory_copy_check_box.setChecked(True)
             self.new_data_directory_has_files_label.show()
         else:
             self.data_directory_copy_check_box.setChecked(False)
             self.new_data_directory_has_files_label.hide()
     else:
         self.data_exists = False
         self.data_directory_copy_check_box.setChecked(True)
         self.new_data_directory_has_files_label.hide()
示例#31
0
 def delete_sources(self):
     """
     Delete the sources for this projector
     """
     msg = QtWidgets.QMessageBox()
     msg.setText(
         translate('OpenLP.SourceSelectForm',
                   'Delete entries for this projector'))
     msg.setInformativeText(
         translate(
             'OpenLP.SourceSelectForm',
             'Are you sure you want to delete ALL user-defined '
             'source input text for this projector?'))
     msg.setStandardButtons(msg.Cancel | msg.Ok)
     msg.setDefaultButton(msg.Cancel)
     ans = msg.exec()
     if ans == msg.Cancel:
         return
     self.projectordb.delete_all_objects(
         ProjectorSource,
         ProjectorSource.projector_id == self.projector.db_item.id)
     self.done(100)
示例#32
0
 def build_file_mask_string(self):
     """
     Build the list of file extensions to be used in the Open file dialog.
     """
     file_type_string = ''
     for controller in self.controllers:
         if self.controllers[controller].enabled():
             file_types = self.controllers[controller].supports + self.controllers[controller].also_supports
             for file_type in file_types:
                 if file_type not in file_type_string:
                     file_type_string += '*.%s ' % file_type
                     self.service_manager.supported_suffixes(file_type)
     self.on_new_file_masks = translate('PresentationPlugin.MediaItem', 'Presentations (%s)') % file_type_string
示例#33
0
 def about():
     about_text = translate('ImagePlugin', '<strong>Image Plugin</strong>'
                            '<br />The image plugin provides displaying of images.<br />One '
                            'of the distinguishing features of this plugin is the ability to '
                            'group a number of images together in the service manager, making '
                            'the displaying of multiple images easier. This plugin can also '
                            'make use of OpenLP\'s "timed looping" feature to create a slide '
                            'show that runs automatically. In addition to this, images from '
                            'the plugin can be used to override the current theme\'s '
                            'background, which renders text-based items like songs with the '
                            'selected image as a background instead of the background '
                            'provided by the theme.')
     return about_text
示例#34
0
 def pre_wizard(self):
     """
     Prepare the UI for the import.
     """
     super(BibleImportForm, self).pre_wizard()
     bible_type = self.field('source_format')
     if bible_type == BibleFormat.WebDownload:
         self.progress_label.setText(
             translate('BiblesPlugin.ImportWizardForm',
                       'Registering Bible...'))
     else:
         self.progress_label.setText(WizardStrings.StartingImport)
     self.application.process_events()
示例#35
0
 def check_search_result(self):
     """
     Checks if the list_view is empty and adds a "No Search Results" item.
     """
     if self.list_view.count():
         return
     message = translate('OpenLP.MediaManagerItem', 'No Search Results')
     item = QtGui.QListWidgetItem(message)
     item.setFlags(QtCore.Qt.NoItemFlags)
     font = QtGui.QFont()
     font.setItalic(True)
     item.setFont(font)
     self.list_view.addItem(item)
示例#36
0
 def on_display_loop(self, field=None):
     if check_item_selected(self.loop_list_widget,
                            translate('OpenLP.LoopManager', 'You must select a loop to play.')):
         item = self.loop_list_widget.currentItem()
         loop_file = os.path.join(self.path, item.data(QtCore.Qt.UserRole))
         vlc_cmd = ['vlc', loop_file, '--one-instance', '--repeat', '-f']
         subprocess.Popen(vlc_cmd)
         # Update GUI to show currently playing loop_thumb
         #f = item.font
         #QtGui.QFont.setBold(True)
         #item.setFont(f)
         #item.setBackgroundColor(QtGui.QColor(0,255,0,255))
         return True
示例#37
0
 def on_current_cell_changed(self, cur_row, cur_col, pre_row, pre_col):
     """
     This function processes all user edits in the table. It is called on each cell change.
     """
     if self.is_deleting:
         self.is_deleting = False
         return
     if self.reloading:
         return
     # only process for editable rows
     if self.tag_table_widget.item(pre_row, 0):
         item = self.tag_table_widget.item(pre_row, pre_col)
         text = item.text()
         errors = None
         if pre_col is EditColumn.Description:
             if not text:
                 errors = translate('OpenLP.FormattingTagForm', 'Description is missing')
         elif pre_col is EditColumn.Tag:
             if not text:
                 errors = translate('OpenLP.FormattingTagForm', 'Tag is missing')
         elif pre_col is EditColumn.StartHtml:
             # HTML edited
             item = self.tag_table_widget.item(pre_row, 3)
             end_html = item.text()
             errors, tag = self.services.start_tag_changed(text, end_html)
             if tag:
                 self.tag_table_widget.setItem(pre_row, 3, QtWidgets.QTableWidgetItem(tag))
             self.tag_table_widget.resizeRowsToContents()
         elif pre_col is EditColumn.EndHtml:
             # HTML edited
             item = self.tag_table_widget.item(pre_row, 2)
             start_html = item.text()
             errors, tag = self.services.end_tag_changed(start_html, text)
             if tag:
                 self.tag_table_widget.setItem(pre_row, 3, QtWidgets.QTableWidgetItem(tag))
         if errors:
             QtWidgets.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), errors,
                                           QtWidgets.QMessageBox.Ok)
         self.tag_table_widget.resizeRowsToContents()
示例#38
0
 def validateCurrentPage(self):
     """
     Validate the current page before moving on to the next page.
     """
     if self.currentPage() == self.welcome_page:
         return True
     elif self.currentPage() == self.available_songs_page:
         items = [
             item
             for item in find_list_widget_items(self.available_list_widget)
             if item.checkState()
         ]
         if not items:
             critical_error_message_box(
                 UiStrings().NISp,
                 translate('SongsPlugin.ExportWizardForm',
                           'You need to add at least one Song to export.'))
             return False
         self.selected_list_widget.clear()
         # Add the songs to the list of selected songs.
         for item in items:
             song = QtWidgets.QListWidgetItem(item.text())
             song.setData(QtCore.Qt.UserRole, item.data(QtCore.Qt.UserRole))
             song.setFlags(QtCore.Qt.ItemIsEnabled)
             self.selected_list_widget.addItem(song)
         return True
     elif self.currentPage() == self.export_song_page:
         if not self.directory_line_edit.text():
             critical_error_message_box(
                 translate('SongsPlugin.ExportWizardForm',
                           'No Save Location specified'),
                 translate('SongsPlugin.ExportWizardForm',
                           'You need to specify a directory.'))
             return False
         return True
     elif self.currentPage() == self.progress_page:
         self.available_list_widget.clear()
         self.selected_list_widget.clear()
         return True
示例#39
0
 def on_data_directory_browse_button_clicked(self):
     """
     Browse for a new data directory location.
     """
     old_root_path = str(self.data_directory_label.text())
     # Get the new directory location.
     new_data_path = QtGui.QFileDialog.getExistingDirectory(
         self,
         translate('OpenLP.AdvancedTab', 'Select Data Directory Location'),
         old_root_path,
         options=QtGui.QFileDialog.ShowDirsOnly)
     # Set the new data path.
     if new_data_path:
         new_data_path = os.path.normpath(new_data_path)
         if self.current_data_path.lower() == new_data_path.lower():
             self.on_data_directory_cancel_button_clicked()
             return
     else:
         return
     # Make sure they want to change the data.
     answer = QtGui.QMessageBox.question(
         self,
         translate('OpenLP.AdvancedTab', 'Confirm Data Directory Change'),
         translate(
             'OpenLP.AdvancedTab', 'Are you sure you want to change the '
             'location of the OpenLP data directory to:\n\n%s\n\nThe data '
             'directory will be changed when OpenLP is closed.').replace(
                 '%s', new_data_path),
         QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes
                                           | QtGui.QMessageBox.No),
         QtGui.QMessageBox.No)
     if answer != QtGui.QMessageBox.Yes:
         return
     # Check if data already exists here.
     self.check_data_overwrite(new_data_path)
     # Save the new location.
     self.main_window.set_new_data_path(new_data_path)
     self.new_data_directory_edit.setText(new_data_path)
     self.data_directory_cancel_button.show()
示例#40
0
    def _get_status(self, status):
        """
        Helper to retrieve status/error codes and convert to strings.

        :param status: Status/Error code
        :returns: (Status/Error code, String)
        """
        if status in ERROR_STRING:
            return ERROR_STRING[status], ERROR_MSG[status]
        elif status in STATUS_STRING:
            return STATUS_STRING[status], ERROR_MSG[status]
        else:
            return status, translate('OpenLP.PJLink1', 'Unknown status')
示例#41
0
 def on_description_updated(self):
     """
     Update the minimum number of characters needed in the description.
     """
     count = int(20 - len(self.description_text_edit.toPlainText()))
     if count < 0:
         count = 0
         self.__button_state(True)
     else:
         self.__button_state(False)
     self.description_word_count.setText(
         translate('OpenLP.ExceptionDialog',
                   'Description characters to enter : %s') % count)
示例#42
0
 def retranslateUi(self):
     """
     This method is called automatically to provide OpenLP with the opportunity to translate the ``MediaManagerItem``
     to another language.
     """
     self.on_new_prompt = translate('MediaPlugin.MediaItem', 'Select Media')
     self.replace_action.setText(UiStrings().ReplaceBG)
     self.replace_action_context.setText(UiStrings().ReplaceBG)
     if 'webkit' in get_media_players()[0]:
         self.replace_action.setToolTip(UiStrings().ReplaceLiveBG)
         self.replace_action_context.setToolTip(UiStrings().ReplaceLiveBG)
     else:
         self.replace_action.setToolTip(UiStrings().ReplaceLiveBGDisabled)
         self.replace_action_context.setToolTip(
             UiStrings().ReplaceLiveBGDisabled)
     self.reset_action.setText(UiStrings().ResetBG)
     self.reset_action.setToolTip(UiStrings().ResetLiveBG)
     self.reset_action_context.setText(UiStrings().ResetBG)
     self.reset_action_context.setToolTip(UiStrings().ResetLiveBG)
     self.automatic = UiStrings().Automatic
     self.display_type_label.setText(
         translate('MediaPlugin.MediaItem', 'Use Player:'))
示例#43
0
 def validate_book(self, new_book_name, abbreviation):
     """
     Validate a book.
     """
     book_regex = re.compile('[\d]*[^\d]+$')
     if not new_book_name:
         self.book_name_edit[abbreviation].setFocus()
         critical_error_message_box(
             UiStrings().EmptyField,
             translate('BiblesPlugin.BibleEditForm',
                       'You need to specify a book name for "%s".') %
             self.book_names[abbreviation])
         return False
     elif not book_regex.match(new_book_name):
         self.book_name_edit[abbreviation].setFocus()
         critical_error_message_box(
             UiStrings().EmptyField,
             translate(
                 'BiblesPlugin.BibleEditForm',
                 'The book name "%s" is not correct.\nNumbers can only be used at the beginning and must\nbe '
                 'followed by one or more non-numeric characters.') %
             new_book_name)
         return False
     for abbr, book in self.books.items():
         if book:
             if abbr == abbreviation:
                 continue
             if self.book_name_edit[abbr].text() == new_book_name:
                 self.book_name_edit[abbreviation].setFocus()
                 critical_error_message_box(
                     translate('BiblesPlugin.BibleEditForm',
                               'Duplicate Book Name'),
                     translate(
                         'BiblesPlugin.BibleEditForm',
                         'The Book Name "%s" has been entered more than once.'
                     ) % new_book_name)
                 return False
     return True
示例#44
0
 def _post_wizard(self):
     """
     Clean up the UI after the process has finished.
     """
     if self.max_progress:
         self.progress_bar.setValue(self.progress_bar.maximum())
         if self.has_run_wizard:
             self.progress_label.setText(
                 translate(
                     'OpenLP.FirstTimeWizard',
                     'Download complete. Click the %s button to return to OpenLP.'
                 ) % clean_button_text(
                     self.buttonText(QtGui.QWizard.FinishButton)))
         else:
             self.progress_label.setText(
                 translate(
                     'OpenLP.FirstTimeWizard',
                     'Download complete. Click the %s button to start OpenLP.'
                 ) % clean_button_text(
                     self.buttonText(QtGui.QWizard.FinishButton)))
     else:
         if self.has_run_wizard:
             self.progress_label.setText(
                 translate('OpenLP.FirstTimeWizard',
                           'Click the %s button to return to OpenLP.') %
                 clean_button_text(
                     self.buttonText(QtGui.QWizard.FinishButton)))
         else:
             self.progress_label.setText(
                 translate('OpenLP.FirstTimeWizard',
                           'Click the %s button to start OpenLP.') %
                 clean_button_text(
                     self.buttonText(QtGui.QWizard.FinishButton)))
     self.finish_button.setVisible(True)
     self.finish_button.setEnabled(True)
     self.cancel_button.setVisible(False)
     self.next_button.setVisible(False)
     self.application.process_events()
示例#45
0
    def load_file(self, data):
        """
        Turn file from Drag and Drop into an array so the Validate code can run it.

        :param data: A dictionary containing the list of files to be loaded and the target
        """
        new_files = []
        error_shown = False
        for file_name in data['files']:
            file_type = file_name.split('.')[-1]
            if file_type.lower() not in self.on_new_file_masks:
                if not error_shown:
                    critical_error_message_box(
                        translate('OpenLP.MediaManagerItem',
                                  'Invalid File Type'),
                        translate('OpenLP.MediaManagerItem',
                                  'Invalid File %s.\nSuffix not supported') %
                        file_name)
                    error_shown = True
            else:
                new_files.append(file_name)
        if new_files:
            self.validate_and_load(new_files, data['target'])
示例#46
0
 def on_status_checkbox_changed(self, status):
     """
     If the status of a plugin is altered, apply the change
     """
     if self.programatic_change or self.active_plugin is None:
         return
     if status:
         self.application.set_busy_cursor()
         self.active_plugin.toggle_status(PluginStatus.Active)
         self.application.set_normal_cursor()
         self.active_plugin.app_startup()
     else:
         self.active_plugin.toggle_status(PluginStatus.Inactive)
     # TODO: Tested at home
     status_text = translate('OpenLP.PluginForm', '{name} (Inactive)')
     if self.active_plugin.status == PluginStatus.Active:
         status_text = translate('OpenLP.PluginForm', '{name} (Active)')
     elif self.active_plugin.status == PluginStatus.Inactive:
         status_text = translate('OpenLP.PluginForm', '{name} (Inactive)')
     elif self.active_plugin.status == PluginStatus.Disabled:
         status_text = translate('OpenLP.PluginForm', '{name} (Disabled)')
     self.plugin_list_widget.currentItem().setText(
         status_text.format(name=self.active_plugin.name_strings['singular']))
示例#47
0
文件: manager.py 项目: jkunle/paul
    def no_authentication_error(self, name):
        """
        Display warning dialog when pin saved for item but projector does not
        require pin.

        :param name: Name from QListWidgetItem
        """
        QtGui.QMessageBox.warning(
            self,
            translate('OpenLP.ProjectorManager',
                      '"%s" No Authentication Error' % name),
            '<br />PIN is set and projector does not require authentication.'
            '<br /><br />Please verify your PIN setting '
            'for projector item "%s"' % name)
示例#48
0
 def set_plugin_text_strings(self):
     """
     Called to define all translatable texts of the plugin.
     """
     # Name PluginList
     self.text_strings[StringContent.Name] = {
         'singular': translate('ImagePlugin', 'Image', 'name singular'),
         'plural': translate('ImagePlugin', 'Images', 'name plural')
     }
     # Name for MediaDockManager, SettingsManager
     self.text_strings[StringContent.VisibleName] = {'title': translate('ImagePlugin', 'Images', 'container title')}
     # Middle Header Bar
     tooltips = {
         'load': translate('ImagePlugin', 'Add new image(s).'),
         'import': '',
         'new': translate('ImagePlugin', 'Add a new image.'),
         'edit': translate('ImagePlugin', 'Edit the selected image.'),
         'delete': translate('ImagePlugin', 'Delete the selected image.'),
         'preview': translate('ImagePlugin', 'Preview the selected image.'),
         'live': translate('ImagePlugin', 'Send the selected image live.'),
         'service': translate('ImagePlugin', 'Add the selected image to the service.')
     }
     self.set_plugin_ui_text_strings(tooltips)
示例#49
0
 def define_output_location(self):
     """
     Triggered when the Directory selection button is clicked
     """
     path = QtGui.QFileDialog.getExistingDirectory(
         self,
         translate('SongUsagePlugin.SongUsageDetailForm',
                   'Output File Location'),
         Settings().value(self.plugin.settings_section +
                          '/last directory export'))
     if path:
         Settings().setValue(
             self.plugin.settings_section + '/last directory export', path)
         self.file_line_edit.setText(path)
示例#50
0
    def _validiate_shortcut(self, changing_action, key_sequence):
        """
        Checks if the given ``changing_action `` can use the given ``key_sequence``. Returns ``True`` if the
        ``key_sequence`` can be used by the action, otherwise displays a dialog and returns ``False``.

        :param changing_action: The action which wants to use the ``key_sequence``.
        :param key_sequence: The key sequence which the action want so use.
        """
        is_valid = True
        for category in self.action_list.categories:
            for action in category.actions:
                shortcuts = self._action_shortcuts(action)
                if key_sequence not in shortcuts:
                    continue
                if action is changing_action:
                    if self.primary_push_button.isChecked() and shortcuts.index(key_sequence) == 0:
                        continue
                    if self.alternate_push_button.isChecked() and shortcuts.index(key_sequence) == 1:
                        continue
                # Have the same parent, thus they cannot have the same shortcut.
                if action.parent() is changing_action.parent():
                    is_valid = False
                # The new shortcut is already assigned, but if both shortcuts are only valid in a different widget the
                # new shortcut is valid, because they will not interfere.
                if action.shortcutContext() in [QtCore.Qt.WindowShortcut, QtCore.Qt.ApplicationShortcut]:
                    is_valid = False
                if changing_action.shortcutContext() in [QtCore.Qt.WindowShortcut, QtCore.Qt.ApplicationShortcut]:
                    is_valid = False
        if not is_valid:
            text = translate('OpenLP.ShortcutListDialog',
                             'The shortcut "{key}" is already assigned to another action, please'
                             ' use a different shortcut.'
                             ).format(key=self.get_shortcut_string(key_sequence))
            self.main_window.warning_message(translate('OpenLP.ShortcutListDialog', 'Duplicate Shortcut'),
                                             text, for_display=True)
            self.dialog_was_shown = True
        return is_valid
示例#51
0
 def retranslateUi(self):
     """
     Translate the UI on the fly
     """
     self.tab_title_visible = UiStrings().Themes
     self.global_group_box.setTitle(
         translate('OpenLP.ThemesTab', 'Global Theme'))
     self.universal_group_box.setTitle(
         translate('OpenLP.ThemesTab', 'Universal Settings'))
     self.wrap_footer_check_box.setText(
         translate('OpenLP.ThemesTab', '&Wrap footer text'))
     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.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.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.'))
示例#52
0
 def do_import(self):
     """
     Receive a single file to import.
     """
     password = self.extract_mdb_password()
     try:
         conn = pyodbc.connect('DRIVER={{Microsoft Access Driver (*.mdb)}};DBQ={source};'
                               'PWD={password}'.format(source=self.import_source, password=password))
     except (pyodbc.DatabaseError, pyodbc.IntegrityError, pyodbc.InternalError, pyodbc.OperationalError) as e:
         log.warning('Unable to connect the OPS Pro database {source}. {error}'.format(source=self.import_source,
                                                                                       error=str(e)))
         # Unfortunately no specific exception type
         self.log_error(self.import_source, translate('SongsPlugin.OPSProImport',
                                                      'Unable to connect the OPS Pro database.'))
         return
     cursor = conn.cursor()
     cursor.execute('SELECT Song.ID, SongNumber, SongBookName, Title, CopyrightText, Version, Origin FROM Song '
                    'LEFT JOIN SongBook ON Song.SongBookID = SongBook.ID ORDER BY Title')
     songs = cursor.fetchall()
     self.import_wizard.progress_bar.setMaximum(len(songs))
     for song in songs:
         if self.stop_import_flag:
             break
         # Type means: 0=Original, 1=Projection, 2=Own
         cursor.execute('SELECT Lyrics, Type, IsDualLanguage FROM Lyrics WHERE SongID = ? AND Type < 2 '
                        'ORDER BY Type DESC', float(song.ID))
         lyrics = cursor.fetchone()
         cursor.execute('SELECT CategoryName FROM Category INNER JOIN SongCategory '
                        'ON Category.ID = SongCategory.CategoryID WHERE SongCategory.SongID = ? '
                        'ORDER BY CategoryName', float(song.ID))
         topics = cursor.fetchall()
         try:
             self.process_song(song, lyrics, topics)
         except Exception as e:
             self.log_error(self.import_source,
                            translate('SongsPlugin.OPSProImport',
                                      '"{title}" could not be imported. {error}').format(title=song.Title, error=e))
示例#53
0
 def on_edit_topic_button_clicked(self):
     """
     Edit a topic.
     """
     topic_id = self._get_current_item_id(self.topics_list_widget)
     if topic_id == -1:
         return
     topic = self.manager.get_object(Topic, topic_id)
     self.topic_form.name = topic.name
     # Save the topic's name for the case that he has to be restored.
     temp_name = topic.name
     if self.topic_form.exec(False):
         topic.name = self.topic_form.name_edit.text()
         if self.check_topic_exists(topic, True):
             if self.manager.save_object(topic):
                 self.reset_topics()
             else:
                 critical_error_message_box(
                     message=translate('SongsPlugin.SongMaintenanceForm',
                                       'Could not save your changes.'))
         elif critical_error_message_box(message=translate(
                 'SongsPlugin.SongMaintenanceForm',
                 'The topic {original} already exists. Would you like to make songs with '
                 'topic {new} use the existing topic {original}?').format(
                     original=topic.name, new=temp_name),
                                         parent=self,
                                         question=True
                                         ) == QtWidgets.QMessageBox.Yes:
             self._merge_objects(topic, self.merge_topics,
                                 self.reset_topics)
         else:
             # We restore the topics's old name.
             topic.name = temp_name
             critical_error_message_box(message=translate(
                 'SongsPlugin.SongMaintenanceForm',
                 'Could not save your modified topic, because it already exists.'
             ))
示例#54
0
 def _perform_wizard(self):
     """
     Run the tasks in the wizard.
     """
     # Set plugin states
     self._increment_progress_bar(
         translate('OpenLP.FirstTimeWizard',
                   'Enabling selected plugins...'))
     self._set_plugin_status(self.songs_check_box, 'songs/status')
     self._set_plugin_status(self.bible_check_box, 'bibles/status')
     self._set_plugin_status(self.presentation_check_box,
                             'presentations/status')
     self._set_plugin_status(self.image_check_box, 'images/status')
     self._set_plugin_status(self.media_check_box, 'media/status')
     self._set_plugin_status(self.remote_check_box, 'remotes/status')
     self._set_plugin_status(self.custom_check_box, 'custom/status')
     self._set_plugin_status(self.song_usage_check_box, 'songusage/status')
     self._set_plugin_status(self.alert_check_box, 'alerts/status')
     if self.web_access:
         if not self._download_selected():
             critical_error_message_box(
                 translate('OpenLP.FirstTimeWizard', 'Download Error'),
                 translate(
                     'OpenLP.FirstTimeWizard',
                     'There was a connection problem while '
                     'downloading, so further downloads will be skipped. Try to re-run '
                     'the First Time Wizard later.'))
     # Set Default Display
     if self.display_combo_box.currentIndex() != -1:
         Settings().setValue('core/monitor',
                             self.display_combo_box.currentIndex())
         self.screens.set_current_display(
             self.display_combo_box.currentIndex())
     # Set Global Theme
     if self.theme_combo_box.currentIndex() != -1:
         Settings().setValue('themes/global theme',
                             self.theme_combo_box.currentText())
示例#55
0
    def retranslateUi(self, alert_dialog):
        """
        Retranslate the UI strings

        :param alert_dialog: The dialog
        """
        alert_dialog.setWindowTitle(translate('AlertsPlugin.AlertForm', 'Alert Message'))
        self.alert_entry_label.setText(translate('AlertsPlugin.AlertForm', 'Alert &text:'))
        self.alert_parameter.setText(translate('AlertsPlugin.AlertForm', '&Parameter:'))
        self.new_button.setText(translate('AlertsPlugin.AlertForm', '&New'))
        self.save_button.setText(translate('AlertsPlugin.AlertForm', '&Save'))
        self.display_button.setText(translate('AlertsPlugin.AlertForm', 'Displ&ay'))
        self.display_close_button.setText(translate('AlertsPlugin.AlertForm', 'Display && Cl&ose'))
示例#56
0
def get_images_filter():
    """
    Returns a filter string for a file dialog containing all the supported image formats.
    """
    global IMAGES_FILTER
    if not IMAGES_FILTER:
        log.debug('Generating images filter.')
        formats = list(
            map(bytes.decode,
                list(map(bytes, QtGui.QImageReader.supportedImageFormats()))))
        visible_formats = '(*.%s)' % '; *.'.join(formats)
        actual_formats = '(*.%s)' % ' *.'.join(formats)
        IMAGES_FILTER = '%s %s %s' % (translate(
            'OpenLP', 'Image Files'), visible_formats, actual_formats)
    return IMAGES_FILTER
    def __init__(self, parent, projectordb, edit=False):
        """
        Build the source select dialog using tabbed interface.

        :param projectordb: ProjectorDB session to use
        """
        log.debug('Initializing SourceSelectTabs()')
        super(SourceSelectTabs, self).__init__(
            parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
        self.setMinimumWidth(350)
        self.projectordb = projectordb
        self.edit = edit
        if self.edit:
            title = translate('OpenLP.SourceSelectForm',
                              'Edit Projector Source Text')
        else:
            title = translate('OpenLP.SourceSelectForm',
                              'Select Projector Source')
        self.setWindowTitle(title)
        self.setObjectName('source_select_tabs')
        self.setWindowIcon(build_icon(':/icon/openlp-log-32x32.png'))
        self.setModal(True)
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.setObjectName('source_select_tabs_layout')
        if is_macosx():
            self.tabwidget = QtWidgets.QTabWidget(self)
        else:
            self.tabwidget = FingerTabWidget(self)
        self.tabwidget.setObjectName('source_select_tabs_tabwidget')
        self.tabwidget.setUsesScrollButtons(False)
        if is_macosx():
            self.tabwidget.setTabPosition(QtWidgets.QTabWidget.North)
        else:
            self.tabwidget.setTabPosition(QtWidgets.QTabWidget.West)
        self.layout.addWidget(self.tabwidget)
        self.setLayout(self.layout)
示例#58
0
def create_valign_selection_widgets(parent):
    """
    Creates a standard label and combo box for asking users to select a vertical alignment.

    :param parent: The parent object. This should be a ``QWidget`` descendant.
    """
    label = QtWidgets.QLabel(parent)
    label.setText(translate('OpenLP.Ui', '&Vertical Align:'))
    combo_box = QtWidgets.QComboBox(parent)
    combo_box.addItems(
        [UiStrings().Top,
         UiStrings().Middle,
         UiStrings().Bottom])
    label.setBuddy(combo_box)
    return label, combo_box
示例#59
0
 def on_copy_theme(self, field=None):
     """
     Copies an existing theme to a new name
     :param field:
     """
     item = self.theme_list_widget.currentItem()
     old_theme_name = item.data(QtCore.Qt.UserRole)
     self.file_rename_form.file_name_edit.setText(
         translate('OpenLP.ThemeManager', 'Copy of %s',
                   'Copy of <theme name>') % old_theme_name)
     if self.file_rename_form.exec(True):
         new_theme_name = self.file_rename_form.file_name_edit.text()
         if self.check_if_theme_exists(new_theme_name):
             theme_data = self.get_theme_data(old_theme_name)
             self.clone_theme_data(theme_data, new_theme_name)
示例#60
0
    def add_import_menu_item(self, import_menu):
        """
        Give the Songs plugin the opportunity to add items to the **Import** menu.

        :param import_menu: The actual **Import** menu item, so that your actions can use it as their parent.
        """
        # Main song import menu item - will eventually be the only one
        self.song_import_item = create_action(
            import_menu,
            'songImportItem',
            text=translate('SongsPlugin', '&Song'),
            tooltip=translate('SongsPlugin',
                              'Import songs using the import wizard.'),
            triggers=self.on_song_import_item_clicked)
        import_menu.addAction(self.song_import_item)
        self.import_songselect_item = create_action(
            import_menu,
            'import_songselect_item',
            text=translate('SongsPlugin', 'CCLI SongSelect'),
            statustip=translate(
                'SongsPlugin',
                'Import songs from CCLI\'s SongSelect service.'),
            triggers=self.on_import_songselect_item_triggered)
        import_menu.addAction(self.import_songselect_item)