def on_edit_auth_button_clicked(self): """ Open the edit auth screen """ self.done(QtWidgets.QDialog.Accepted) settings_form = Registry().get('settings_form') settings_form.exec(translate('PlanningCenterPlugin', 'PlanningCenter'))
def handle_db_error(plugin_name, db_file_name): """ Log and report to the user that a database cannot be loaded :param plugin_name: Name of plugin :param db_file_name: File name of database :return: None """ db_path = get_db_path(plugin_name, db_file_name) log.exception('Error loading database: {db}'.format(db=db_path)) critical_error_message_box( translate('OpenLP.Manager', 'Database Error'), translate( 'OpenLP.Manager', 'OpenLP cannot load your database.\n\nDatabase: {db}').format( db=db_path))
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_path = Path(gettempdir(), 'openlp') if not db_dir_path.exists(): return song_db_paths = [] song_count = 0 for db_file_path in db_dir_path.glob('songs_*.sqlite'): self.application.process_events() song_db_paths.append(db_file_path) song_count += SongsPlugin._count_songs(db_file_path) if not song_db_paths: return self.application.process_events() progress = QtWidgets.QProgressDialog(self.main_window) progress.setWindowModality(QtCore.Qt.WindowModal) progress.setWindowTitle(translate('SongsPlugin', 'Importing Songs')) progress.setLabelText(UiStrings().StartingImport) progress.setCancelButton(None) progress.setRange(0, song_count) progress.setMinimumDuration(0) progress.forceShow() self.application.process_events() for db_path in song_db_paths: importer = OpenLPSongImport(self.manager, file_path=db_path) importer.do_import(progress) self.application.process_events() progress.setValue(song_count) self.media_item.on_search_text_button_clicked()
def __init__(self, parent): """ Constructor """ self.icon_path = UiIcons().video player_translated = translate('OpenLP.MediaTab', 'Media') super(MediaTab, self).__init__(parent, 'Media', player_translated)
def update_preview_text(self): """ Creates the html text and updates the html of *self.document*. """ html_data = self._add_element('html') self._add_element('head', parent=html_data) self._add_element('title', self.title_line_edit.text(), html_data.head) css_path = AppLocation.get_data_path() / 'serviceprint' / 'service_print.css' custom_css = get_text_file_string(css_path) if not custom_css: custom_css = DEFAULT_CSS self._add_element('style', custom_css, html_data.head, attribute=('type', 'text/css')) self._add_element('body', parent=html_data) self._add_element('h1', html.escape(self.title_line_edit.text()), html_data.body, class_id='serviceTitle') for index, item in enumerate(self.service_manager.service_items): self._add_preview_item(html_data.body, item['service_item'], index) if not self.show_chords_check_box.isChecked(): # Remove chord row and spacing span elements when not printing chords for chord_row in html_data.find_class('chordrow'): chord_row.drop_tree() for spacing_span in html_data.find_class('chordspacing'): spacing_span.drop_tree() # Add the custom service notes: if self.footer_text_edit.toPlainText(): div = self._add_element('div', parent=html_data.body, class_id='customNotes') self._add_element( 'span', translate('OpenLP.ServiceManager', 'Service Notes: '), div, class_id='customNotesTitle') self._add_element('span', html.escape(self.footer_text_edit.toPlainText()), div, class_id='customNotesText') self.document.setHtml(lxml.html.tostring(html_data).decode()) self.preview_widget.updatePreview()
def on_new_click(self): """ Create a new alert. """ if not self.alert_text_edit.text(): QtWidgets.QMessageBox.information( self, translate('AlertsPlugin.AlertForm', 'New Alert'), translate( 'AlertsPlugin.AlertForm', 'You haven\'t specified any text for your alert. \n' 'Please type in some text before clicking New.')) else: alert = AlertItem() alert.text = self.alert_text_edit.text() self.manager.save_object(alert) self.load_list()
def do_import(self): """ Receive a single file or a list of files to import. """ self.encoding = None self.import_source = Path(self.import_source) with self.import_source.open('rt', errors='ignore') as songs_file: self.import_wizard.progress_bar.setMaximum(0) tag = '' text = '' for file_line in songs_file: if self.stop_import_flag: break file_text = file_line.rstrip() if file_text and file_text[0] == '#': try: self.process_section(tag, text.rstrip()) except ValueError: log.exception('Missing data in {name}'.format(name=self.import_source)) self.log_error(self.import_source, translate('SongsPlugin.SongProImport', 'File is not a valid SongPro file.')) return tag = file_text[1:] text = '' else: text += file_line self.finish()
def on_add_book_button_clicked(self): """ Add a book to the list. """ if self.song_book_form.exec(): book = Book.populate(name=self.song_book_form.name_edit.text(), publisher=self.song_book_form.publisher_edit.text()) if self.check_song_book_exists(book): if self.manager.save_object(book): self.reset_song_books() else: critical_error_message_box( message=translate('SongsPlugin.SongMaintenanceForm', 'Could not add your book.')) else: critical_error_message_box( message=translate('SongsPlugin.SongMaintenanceForm', 'This book already exists.'))
def load_themes(self): """ Loads the theme lists and triggers updates across the whole system using direct calls or core functions and events for the plugins. The plugins will call back in to get the real list if they want it. """ self.theme_list = [] self.theme_list_widget.clear() files = AppLocation.get_files(self.settings_section, '.png') # Sort the themes by its name considering language specific files.sort(key=lambda file_name: get_locale_key(str(file_name))) # now process the file list of png files for file in files: # check to see file is in theme root directory theme_path = self.theme_path / file if theme_path.exists(): text_name = theme_path.stem if text_name == self.global_theme: name = translate('OpenLP.ThemeManager', '{name} (default)').format(name=text_name) else: name = text_name thumb_path = self.thumb_path / '{name}.png'.format(name=text_name) item_name = QtWidgets.QListWidgetItem(name) if validate_thumb(theme_path, thumb_path): icon = build_icon(thumb_path) else: icon = create_thumb(theme_path, thumb_path) item_name.setIcon(icon) item_name.setData(QtCore.Qt.UserRole, text_name) self.theme_list_widget.addItem(item_name) self.theme_list.append(text_name) self._push_themes()
def on_clone_click(self): """ Clone a Song """ log.debug('on_clone_click') if check_item_selected(self.list_view, UiStrings().SelectEdit): self.edit_item = self.list_view.currentItem() item_id = self.edit_item.data(QtCore.Qt.UserRole) old_song = self.plugin.manager.get_object(Song, item_id) song_xml = self.open_lyrics.song_to_xml(old_song) new_song = self.open_lyrics.xml_to_song(song_xml) new_song.title = '{title} <{text}>'.format( title=new_song.title, text=translate('SongsPlugin.MediaItem', 'copy', 'For song cloning')) # Copy audio files from the old to the new song if len(old_song.media_files) > 0: save_path = AppLocation.get_section_data_path( self.plugin.name) / 'audio' / str(new_song.id) create_paths(save_path) for media_file in old_song.media_files: new_media_file_path = save_path / media_file.file_path.name copyfile(media_file.file_path, new_media_file_path) new_media_file = MediaFile() new_media_file.file_path = new_media_file_path new_media_file.type = media_file.type new_media_file.weight = media_file.weight new_song.media_files.append(new_media_file) self.plugin.manager.save_object(new_song) self.on_song_list_load()
def add_custom_context_actions(self): create_widget_action(self.list_view, separator=True) create_widget_action(self.list_view, text=translate('OpenLP.MediaManagerItem', '&Clone'), icon=UiIcons().clone, triggers=self.on_clone_click)
def on_delete_click(self): """ Remove a song from the list and database """ if check_item_selected(self.list_view, UiStrings().SelectDelete): items = self.list_view.selectedItems() if QtWidgets.QMessageBox.question( self, UiStrings().ConfirmDelete, translate( 'SongsPlugin.MediaItem', 'Are you sure you want to delete the following songs?') + '\n\n- {songs}'.format( songs='\n- '.join([item.text() for item in items])), defaultButton=QtWidgets.QMessageBox.Yes ) == QtWidgets.QMessageBox.No: return self.application.set_busy_cursor() self.main_window.display_progress_bar(len(items)) for item in items: item_id = item.data(QtCore.Qt.UserRole) delete_song(item_id, self.plugin) self.main_window.increment_progress_bar() self.main_window.finished_progress_bar() self.application.set_normal_cursor() self.on_search_text_button_clicked()
def _create_report(self): """ Create an exception report. """ openlp_version = get_version() description = self.description_text_edit.toPlainText() traceback = self.exception_text_edit.toPlainText() system = translate( 'OpenLP.ExceptionForm', 'Platform: {platform}\n').format(platform=platform.platform()) library_versions = get_library_versions() library_versions['PyUNO'] = self._get_pyuno_version() libraries = '\n'.join([ '{}: {}'.format(library, version) for library, version in library_versions.items() ]) if is_linux(): if os.environ.get('KDE_FULL_SESSION') == 'true': system += 'Desktop: KDE SC\n' elif os.environ.get('GNOME_DESKTOP_SESSION_ID'): system += 'Desktop: GNOME\n' elif os.environ.get('DESKTOP_SESSION') == 'xfce': system += 'Desktop: Xfce\n' # NOTE: Keys match the expected input for self.report_text.format() return { 'version': openlp_version, 'description': description, 'traceback': traceback, 'system': system, 'libs': libraries }
def set_controller_text(self, checkbox, controller): if checkbox.isEnabled(): checkbox.setText(controller.name) else: checkbox.setText( translate('PresentationPlugin.PresentationTab', '{name} (unavailable)').format(name=controller.name))
def on_delete_click(self): """ Remove a custom item from the list and database """ if check_item_selected(self.list_view, UiStrings().SelectDelete): items = self.list_view.selectedIndexes() if QtWidgets.QMessageBox.question( self, UiStrings().ConfirmDelete, translate( 'CustomPlugin.MediaItem', 'Are you sure you want to delete the "{items:d}" ' 'selected custom slide(s)?').format(items=len(items)), defaultButton=QtWidgets.QMessageBox.Yes ) == QtWidgets.QMessageBox.No: return row_list = [ item.row() for item in self.list_view.selectedIndexes() ] row_list.sort(reverse=True) id_list = [(item.data(QtCore.Qt.UserRole)) for item in self.list_view.selectedIndexes()] for id in id_list: self.plugin.db_manager.delete_object(CustomSlide, id) self.on_search_text_button_clicked()
def print_song_usage(self, item): """ Song Usage for which has been printed :param item: Item printed """ self._add_song_usage(translate('SongUsagePlugin', 'printed'), item)
def display_song_usage(self, item): """ Song Usage for which has been displayed :param item: Item displayed """ self._add_song_usage(translate('SongUsagePlugin', 'display'), item)
def __init__(self, parent): """ Constructor """ self.icon_path = UiIcons().theme theme_translated = translate('OpenLP.ThemesTab', 'Themes') super(ThemesTab, self).__init__(parent, 'Themes', theme_translated)
def contextMenuEvent(self, event): """ Provide the context menu for the text edit region. """ popup_menu = self.createStandardContextMenu() # Select the word under the cursor. cursor = self.textCursor() # only select text if not already selected if not cursor.hasSelection(): cursor.select(QtGui.QTextCursor.WordUnderCursor) self.setTextCursor(cursor) # Add menu with available languages. if ENCHANT_AVAILABLE: lang_menu = QtWidgets.QMenu( translate('OpenLP.SpellTextEdit', 'Language:')) for lang in enchant.list_languages(): action = create_action(lang_menu, lang, text=lang, checked=lang == self.dictionary.tag) lang_menu.addAction(action) popup_menu.insertSeparator(popup_menu.actions()[0]) popup_menu.insertMenu(popup_menu.actions()[0], lang_menu) lang_menu.triggered.connect(self.set_language) # Check if the selected word is misspelled and offer spelling suggestions if it is. if ENCHANT_AVAILABLE and self.textCursor().hasSelection(): text = self.textCursor().selectedText() if not self.dictionary.check(text): spell_menu = QtWidgets.QMenu( translate('OpenLP.SpellTextEdit', 'Spelling Suggestions')) for word in self.dictionary.suggest(text): action = SpellAction(word, spell_menu) action.correct.connect(self.correct_word) spell_menu.addAction(action) # Only add the spelling suggests to the menu if there are suggestions. if spell_menu.actions(): popup_menu.insertMenu(popup_menu.actions()[0], spell_menu) tag_menu = QtWidgets.QMenu( translate('OpenLP.SpellTextEdit', 'Formatting Tags')) if self.formatting_tags_allowed: for html in FormattingTags.get_html_tags(): action = SpellAction(html['desc'], tag_menu) action.correct.connect(self.html_tag) tag_menu.addAction(action) popup_menu.insertSeparator(popup_menu.actions()[0]) popup_menu.insertMenu(popup_menu.actions()[0], tag_menu) popup_menu.exec(event.globalPos())
def _process_details(self, html_details): # convert <br> into new lines html_details = re.sub(r'<br>', '\n', html_details) # covert formatting tags from list to dict to I can do arbitrary lookups FormattingTags.load_tags() openlp_formatting_tags = {} for formatting_tag in FormattingTags.get_html_tags(): openlp_formatting_tags[formatting_tag['desc']] = {} openlp_formatting_tags[formatting_tag['desc']]['start tag'] = formatting_tag['start tag'] openlp_formatting_tags[formatting_tag['desc']]['end tag'] = formatting_tag['end tag'] # convert bold html_details = re.sub(r'<strong>(.*?)</strong>', r"{start}\1{end}".format( start=openlp_formatting_tags[ translate('OpenLP.FormattingTags', 'Bold')]['start tag'], end=openlp_formatting_tags[ translate('OpenLP.FormattingTags', 'Bold')]['end tag']), html_details) # convert underline html_details = re.sub(r'<span style="text-decoration: underline;">(.*?)</span>', r"{start}\1{end}".format( start=openlp_formatting_tags[ translate('OpenLP.FormattingTags', 'Underline')]['start tag'], end=openlp_formatting_tags[ translate('OpenLP.FormattingTags', 'Underline')]['end tag']), html_details) # convert italics html_details = re.sub(r'<em>(.*?)</em>', r"{start}\1{end}".format( start=openlp_formatting_tags[ translate('OpenLP.FormattingTags', 'Italics')]['start tag'], end=openlp_formatting_tags[ translate('OpenLP.FormattingTags', 'Italics')]['end tag']), html_details) # convert PlanningCenter colors to OpenLP base tags color_lookup = { 'Red': 'ff0000', 'Black': '000000', 'Blue': '0000ff', 'Yellow': 'ffff00', 'Green': '008000', 'Pink': 'ff99cc', 'Orange': 'ff6600', 'Purple': '800080', 'White': 'ffffff', } for color in color_lookup.keys(): html_details = re.sub(r'<span style="color: #{number};">(.*?)</span>'.format(number=color_lookup[color]), r"{start}\1{end}".format( start=openlp_formatting_tags[ translate('OpenLP.FormattingTags', color)]['start tag'], end=openlp_formatting_tags[ translate('OpenLP.FormattingTags', color)]['end tag']), html_details) # throw away the rest of the html html_details = re.sub(r'(<!--.*?-->|<[^>]*>)', '', html_details) return html_details
def add_tools_menu_item(self, tools_menu): """ Give the alerts plugin the opportunity to add items to the **Tools** menu. :param tools_menu: The actual **Tools** menu item, so that your actions can use it as their parent. """ log.info('add tools menu') self.tools_alert_item = create_action( tools_menu, 'toolsAlertItem', text=translate('AlertsPlugin', '&Alert'), icon=UiIcons().alert, statustip=translate('AlertsPlugin', 'Show an alert message.'), visible=False, can_shortcuts=True, triggers=self.on_alerts_trigger) self.main_window.tools_menu.addAction(self.tools_alert_item)
def about(): about_text = translate( 'CustomPlugin', '<strong>Custom Slide Plugin </strong><br />The custom slide plugin ' 'provides the ability to set up custom text slides that can be displayed on the screen ' 'the same way songs are. This plugin provides greater freedom over the songs plugin.' ) return about_text
def on_add_topic_button_clicked(self): """ Add a topic to the list. """ if self.topic_form.exec(): topic = Topic.populate(name=self.topic_form.name) if self.check_topic_exists(topic): if self.manager.save_object(topic): self.reset_topics() else: critical_error_message_box( message=translate('SongsPlugin.SongMaintenanceForm', 'Could not add your topic.')) else: critical_error_message_box( message=translate('SongsPlugin.SongMaintenanceForm', 'This topic already exists.'))
def accept(self): if not self.language_combo_box.currentText(): critical_error_message_box(message=translate( 'BiblesPlugin.LanguageForm', 'You need to choose a language.')) self.language_combo_box.setFocus() return False else: return QDialog.accept(self)
def pre_wizard(self): """ Perform pre export tasks. """ super(SongExportForm, self).pre_wizard() self.progress_label.setText( translate('SongsPlugin.ExportWizardForm', 'Starting export...')) self.application.process_events()
def retranslate_ui(self, song_usage_detail_dialog): """ Retranslate the UI :param song_usage_detail_dialog: """ song_usage_detail_dialog.setWindowTitle( translate('SongUsagePlugin.SongUsageDetailForm', 'Song Usage Extraction')) self.date_range_group_box.setTitle( translate('SongUsagePlugin.SongUsageDetailForm', 'Select Date Range')) self.to_label.setText( translate('SongUsagePlugin.SongUsageDetailForm', 'to')) self.file_group_box.setTitle( translate('SongUsagePlugin.SongUsageDetailForm', 'Report Location'))
def about(): """ Return the about text for the plugin manager """ about_text = translate( 'MediaPlugin', '<strong>Media Plugin</strong>' '<br />The media plugin provides playback of audio and video.') return about_text
def retranslateUi(self): self.background_color_group_box.setTitle(UiStrings().BackgroundColor) self.background_color_label.setText(UiStrings().BackgroundColorColon) self.information_label.setText( translate( 'ImagesPlugin.ImageTab', 'Visible background for images with aspect ratio different to screen.' ))
def on_display_clicked(self, is_checked): if not is_checked: critical_error_message_box( translate('OpenLP.ScreensTab', 'Select a Display'), translate( 'OpenLP.ScreensTab', 'You need to select at least one screen to be ' 'used as a display. Select the screen you wish to use as a display, ' 'and check the checkbox for that screen.'), parent=self, question=False) self.use_screen_check_box.setChecked(True) self.display_group_box.setChecked(True) else: for screen in self.screens: screen.is_display = False self.current_screen.is_display = True
def get_display_screen_list(self): """ Returns a list with the screens. This should only be used to display available screens to the user:: ['Screen 1 (primary)', 'Screen 2'] """ screen_list = [] for screen in self.screens: screen_name = '{name} {number:d}'.format(name=translate( 'OpenLP.ScreenList', 'Screen'), number=screen.number + 1) if screen.is_primary: screen_name = '{name} ({primary})'.format( name=screen_name, primary=translate('OpenLP.ScreenList', 'primary')) screen_list.append(screen_name) return screen_list