def _process_formatting_tags(self, song_xml, temporary): """ Process the formatting tags from the song and either add missing tags temporary or permanently to the formatting tag list. """ if not hasattr(song_xml, u'format'): return found_tags = [] for tag in song_xml.format.tags.getchildren(): name = tag.get(u'name') if name is None: continue start_tag = u'{%s}' % name[:5] # Some tags have only start tag e.g. {br} end_tag = u'{/' + name[:5] + u'}' if hasattr(tag, 'close') else u'' openlp_tag = { u'desc': name, u'start tag': start_tag, u'end tag': end_tag, u'start html': tag.open.text, # Some tags have only start html e.g. {br} u'end html': tag.close.text if hasattr(tag, 'close') else u'', u'protected': False, } # Add 'temporary' key in case the formatting tag should not be # saved otherwise it is supposed that formatting tag is permanent. if temporary: openlp_tag[u'temporary'] = temporary found_tags.append(openlp_tag) existing_tag_ids = [tag[u'start tag'] for tag in FormattingTags.get_html_tags()] new_tags = [tag for tag in found_tags if tag[u'start tag'] not in existing_tag_ids] FormattingTags.add_html_tags(new_tags) FormattingTags.save_html_tags()
def _setup(self): """ Set up the class. This method is mocked out by the tests. """ self.services = FormattingTagController() self.tag_table_widget.itemSelectionChanged.connect(self.on_row_selected) self.new_button.clicked.connect(self.on_new_clicked) self.delete_button.clicked.connect(self.on_delete_clicked) self.tag_table_widget.currentCellChanged.connect(self.on_current_cell_changed) self.button_box.rejected.connect(self.close) # Forces reloading of tags from openlp configuration. FormattingTags.load_tags() self.is_deleting = False self.reloading = False
def _reloadTable(self): """ Reset List for loading. """ self.reloading = True self.tag_table_widget_read.clearContents() self.tag_table_widget_read.setRowCount(0) self.tag_table_widget.clearContents() self.tag_table_widget.setRowCount(0) self.new_button.setEnabled(True) self.delete_button.setEnabled(False) for line_number, html in enumerate(FormattingTags.get_html_tags()): if html["protected"]: line = self.tag_table_widget_read.rowCount() self.tag_table_widget_read.setRowCount(line + 1) self.tag_table_widget_read.setItem(line, 0, QtGui.QTableWidgetItem(html["desc"])) self.tag_table_widget_read.setItem(line, 1, QtGui.QTableWidgetItem(self._strip(html["start tag"]))) self.tag_table_widget_read.setItem(line, 2, QtGui.QTableWidgetItem(html["start html"])) self.tag_table_widget_read.setItem(line, 3, QtGui.QTableWidgetItem(html["end html"])) self.tag_table_widget_read.resizeRowsToContents() else: line = self.tag_table_widget.rowCount() self.tag_table_widget.setRowCount(line + 1) self.tag_table_widget.setItem(line, 0, QtGui.QTableWidgetItem(html["desc"])) self.tag_table_widget.setItem(line, 1, QtGui.QTableWidgetItem(self._strip(html["start tag"]))) self.tag_table_widget.setItem(line, 2, QtGui.QTableWidgetItem(html["start html"])) self.tag_table_widget.setItem(line, 3, QtGui.QTableWidgetItem(html["end html"])) self.tag_table_widget.resizeRowsToContents() # Permanent (persistent) tags do not have this key html["temporary"] = False self.reloading = False
def _reloadTable(self): """ Reset List for loading. """ self.reloading = True self.tag_table_widget_read.clearContents() self.tag_table_widget_read.setRowCount(0) self.tag_table_widget.clearContents() self.tag_table_widget.setRowCount(0) self.new_button.setEnabled(True) self.delete_button.setEnabled(False) for line_number, html in enumerate(FormattingTags.get_html_tags()): if html['protected']: line = self.tag_table_widget_read.rowCount() self.tag_table_widget_read.setRowCount(line + 1) self.tag_table_widget_read.setItem(line, 0, QtGui.QTableWidgetItem(html['desc'])) self.tag_table_widget_read.setItem(line, 1, QtGui.QTableWidgetItem(self._strip(html['start tag']))) self.tag_table_widget_read.setItem(line, 2, QtGui.QTableWidgetItem(html['start html'])) self.tag_table_widget_read.setItem(line, 3, QtGui.QTableWidgetItem(html['end html'])) self.tag_table_widget_read.resizeRowsToContents() else: line = self.tag_table_widget.rowCount() self.tag_table_widget.setRowCount(line + 1) self.tag_table_widget.setItem(line, 0, QtGui.QTableWidgetItem(html['desc'])) self.tag_table_widget.setItem(line, 1, QtGui.QTableWidgetItem(self._strip(html['start tag']))) self.tag_table_widget.setItem(line, 2, QtGui.QTableWidgetItem(html['start html'])) self.tag_table_widget.setItem(line, 3, QtGui.QTableWidgetItem(html['end html'])) self.tag_table_widget.resizeRowsToContents() # Permanent (persistent) tags do not have this key html['temporary'] = False self.reloading = False
def get_start_tags(raw_text): """ Tests the given text for not closed formatting tags and returns a tuple consisting of three unicode strings:: ('{st}{r}Text text text{/r}{/st}', '{st}{r}', '<strong><span style="-webkit-text-fill-color:red">') The first unicode string is the text, with correct closing tags. The second unicode string are OpenLP's opening formatting tags and the third unicode string the html opening formatting tags. :param raw_text: The text to test. The text must **not** contain html tags, only OpenLP formatting tags are allowed:: {st}{r}Text text text """ raw_tags = [] html_tags = [] for tag in FormattingTags.get_html_tags(): if tag['start tag'] == '{br}': continue if raw_text.count(tag['start tag']) != raw_text.count(tag['end tag']): raw_tags.append((raw_text.find(tag['start tag']), tag['start tag'], tag['end tag'])) html_tags.append((raw_text.find(tag['start tag']), tag['start html'])) # Sort the lists, so that the tags which were opened first on the first slide (the text we are checking) will be # opened first on the next slide as well. raw_tags.sort(key=lambda tag: tag[0]) html_tags.sort(key=lambda tag: tag[0]) # Create a list with closing tags for the raw_text. end_tags = [] start_tags = [] for tag in raw_tags: start_tags.append(tag[1]) end_tags.append(tag[2]) end_tags.reverse() # Remove the indexes. html_tags = [tag[1] for tag in html_tags] return raw_text + ''.join(end_tags), ''.join(start_tags), ''.join(html_tags)
def test_find_formatting_tags(self): """ Test that find_formatting_tags works as expected """ # GIVEN: Lyrics with formatting tags and a empty list of formatting tags lyrics = '{st}Amazing {r}grace{/r} how sweet the sound' tags = [] FormattingTags.load_tags() # WHEN: Detecting active formatting tags active_tags = find_formatting_tags(lyrics, tags) # THEN: The list of active tags should contain only 'st' assert [ 'st' ] == active_tags, 'The list of active tags should contain only "st"'
def _get_missing_tags(self, text): """ Tests the given text for not closed formatting tags and returns a tuple consisting of two unicode strings:: (u'{st}{r}', u'{/r}{/st}') The first unicode string are the start tags (for the next slide). The second unicode string are the end tags. ``text`` The text to test. The text must **not** contain html tags, only OpenLP formatting tags are allowed:: {st}{r}Text text text """ tags = [] for tag in FormattingTags.get_html_tags(): if tag[u'start tag'] == u'{br}': continue if text.count(tag[u'start tag']) != text.count(tag[u'end tag']): tags.append((text.find(tag[u'start tag']), tag[u'start tag'], tag[u'end tag'])) # Sort the lists, so that the tags which were opened first on the first # slide (the text we are checking) will be opened first on the next # slide as well. tags.sort(key=lambda tag: tag[0]) end_tags = [] start_tags = [] for tag in tags: start_tags.append(tag[1]) end_tags.append(tag[2]) end_tags.reverse() return u''.join(start_tags), u''.join(end_tags)
def _get_missing_tags(self, text): """ Tests the given text for not closed formatting tags and returns a tuple consisting of two unicode strings:: ('{st}{r}', '{/r}{/st}') The first unicode string are the start tags (for the next slide). The second unicode string are the end tags. :param text: The text to test. The text must **not** contain html tags, only OpenLP formatting tags are allowed:: {st}{r}Text text text """ tags = [] for tag in FormattingTags.get_html_tags(): if tag['start tag'] == '{br}': continue if text.count(tag['start tag']) != text.count(tag['end tag']): tags.append((text.find(tag['start tag']), tag['start tag'], tag['end tag'])) # Sort the lists, so that the tags which were opened first on the first slide (the text we are checking) will # be opened first on the next slide as well. tags.sort(key=lambda tag: tag[0]) end_tags = [] start_tags = [] for tag in tags: start_tags.append(tag[1]) end_tags.append(tag[2]) end_tags.reverse() return ''.join(start_tags), ''.join(end_tags)
def test_expand_chords_for_printing(self): """ Test that the expanding of chords for printing works as expected. """ # GIVEN: A lyrics-line with chords text_with_chords = '{st}[D]Amazing {r}gr[D7]ace{/r} how [G]sweet the [D]sound [F]{/st}' FormattingTags.load_tags() # WHEN: Expanding the chords text_with_expanded_chords = expand_chords_for_printing( text_with_chords, '{br}') # THEN: We should get html that looks like below expected_html = '<table class="line" width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td><table ' \ 'class="segment" cellpadding="0" cellspacing="0" border="0" align="left"><tr class="chordrow">'\ '<td class="chord"> </td><td class="chord">D</td></tr><tr><td class="lyrics">{st}{/st}' \ '</td><td class="lyrics">{st}Amazing {/st}</td></tr></table><table class="segment" ' \ 'cellpadding="0" cellspacing="0" border="0" align="left"><tr class="chordrow">' \ '<td class="chord"> </td><td class="chord">D7</td></tr><tr><td class="lyrics">{st}{r}gr' \ '{/r}{/st}</td><td class="lyrics">{r}{st}ace{/r} {/st}</td></tr></table><table ' \ 'class="segment" cellpadding="0" cellspacing="0" border="0" align="left"><tr class="chordrow">'\ '<td class="chord"> </td></tr><tr><td class="lyrics">{st} {/st}</td></tr></table>' \ '<table class="segment" cellpadding="0" cellspacing="0" border="0" align="left"><tr ' \ 'class="chordrow"><td class="chord"> </td></tr><tr><td class="lyrics">{st}how {/st}' \ '</td></tr></table><table class="segment" cellpadding="0" cellspacing="0" border="0" ' \ 'align="left"><tr class="chordrow"><td class="chord">G</td></tr><tr><td class="lyrics">{st}' \ 'sweet {/st}</td></tr></table><table class="segment" cellpadding="0" cellspacing="0" ' \ 'border="0" align="left"><tr class="chordrow"><td class="chord"> </td></tr><tr><td ' \ 'class="lyrics">{st}the {/st}</td></tr></table><table class="segment" cellpadding="0" ' \ 'cellspacing="0" border="0" align="left"><tr class="chordrow"><td class="chord">D</td></tr>' \ '<tr><td class="lyrics">{st}sound {/st}</td></tr></table><table class="segment" ' \ 'cellpadding="0" cellspacing="0" border="0" align="left"><tr class="chordrow"><td ' \ 'class="chord"> </td></tr><tr><td class="lyrics">{st} {/st}</td></tr></table>' \ '<table class="segment" cellpadding="0" cellspacing="0" border="0" align="left"><tr ' \ 'class="chordrow"><td class="chord">F</td></tr><tr><td class="lyrics">{st}{/st} </td>' \ '</tr></table></td></tr></table>' assert expected_html == text_with_expanded_chords, 'The expanded chords should look as expected!'
def test_service_item_load_song_and_audio_from_service(self): """ Test the Service Item - adding a song slide from a saved service """ # GIVEN: A new service item and a mocked add icon function service_item = ServiceItem(None) service_item.add_icon = MagicMock() FormattingTags.load_tags() # WHEN: We add a custom from a saved service line = convert_file_service_item(TEST_PATH, 'serviceitem-song-linked-audio.osj') service_item.set_from_service(line, '/test/') # THEN: We should get back a valid service item assert service_item.is_valid is True, 'The new service item should be valid' assert 0 == len(service_item._display_frames ), 'The service item should have no display frames' assert 7 == len(service_item.capabilities ), 'There should be 7 default custom item capabilities' # WHEN: We render the frames of the service item service_item.render(True) # THEN: The frames should also be valid assert 'Amazing Grace' == service_item.get_display_title( ), 'The title should be "Amazing Grace"' assert CLEANED_VERSE[:-1] == service_item.get_frames()[0]['text'], \ 'The returned text matches the input, except the last line feed' assert RENDERED_VERSE.split('\n', 1)[0] == service_item.get_rendered_frame(1), \ 'The first line has been returned' assert 'Amazing Grace! how sweet the s' == service_item.get_frame_title(0), \ '"Amazing Grace! how sweet the s" has been returned as the title' assert '’Twas grace that taught my hea' == service_item.get_frame_title(1), \ '"’Twas grace that taught my hea" has been returned as the title' assert Path('/test/amazing_grace.mp3') == service_item.background_audio[0], \ '"/test/amazing_grace.mp3" should be in the background_audio list'
def test_service_item_load_custom_from_service(self): """ Test the Service Item - adding a custom slide from a saved service """ # GIVEN: A new service item and a mocked add icon function service_item = ServiceItem(None) service_item.add_icon = MagicMock() FormattingTags.load_tags() # WHEN: We add a custom from a saved service line = convert_file_service_item(TEST_PATH, 'serviceitem_custom_1.osj') service_item.set_from_service(line) # THEN: We should get back a valid service item assert service_item.is_valid is True, 'The new service item should be valid' assert_length(0, service_item._display_frames, 'The service item should have no display frames') assert_length(5, service_item.capabilities, 'There should be 5 default custom item capabilities') # WHEN: We render the frames of the service item service_item.render(True) # THEN: The frames should also be valid assert 'Test Custom' == service_item.get_display_title( ), 'The title should be "Test Custom"' assert CLEANED_VERSE[:-1] == service_item.get_frames()[0]['text'], \ 'The returned text matches the input, except the last line feed' assert RENDERED_VERSE.split('\n', 1)[0] == service_item.get_rendered_frame(1), \ 'The first line has been returned' assert 'Slide 1' == service_item.get_frame_title( 0), '"Slide 1" has been returned as the title' assert 'Slide 2' == service_item.get_frame_title( 1), '"Slide 2" has been returned as the title' assert '' == service_item.get_frame_title( 2), 'Blank has been returned as the title of slide 3'
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 contextMenuEvent(self, event): """ Provide the context menu for the text edit region. """ popupMenu = 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 = QtGui.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) popupMenu.insertSeparator(popupMenu.actions()[0]) popupMenu.insertMenu(popupMenu.actions()[0], lang_menu) QtCore.QObject.connect(lang_menu, QtCore.SIGNAL(u'triggered(QAction*)'), self.setLanguage) # 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 = QtGui.QMenu(translate('OpenLP.SpellTextEdit', 'Spelling Suggestions')) for word in self.dictionary.suggest(text): action = SpellAction(word, spell_menu) action.correct.connect(self.correctWord) spell_menu.addAction(action) # Only add the spelling suggests to the menu if there are # suggestions. if spell_menu.actions(): popupMenu.insertMenu(popupMenu.actions()[0], spell_menu) tagMenu = QtGui.QMenu(translate('OpenLP.SpellTextEdit', 'Formatting Tags')) if self.formattingTagsAllowed: for html in FormattingTags.get_html_tags(): action = SpellAction(html[u'desc'], tagMenu) action.correct.connect(self.htmlTag) tagMenu.addAction(action) popupMenu.insertSeparator(popupMenu.actions()[0]) popupMenu.insertMenu(popupMenu.actions()[0], tagMenu) popupMenu.exec_(event.globalPos())
def html_tag(self, tag): """ Replaces the selected text with word. """ for html in FormattingTags.get_html_tags(): if tag == html['desc']: cursor = self.textCursor() if self.textCursor().hasSelection(): text = cursor.selectedText() cursor.beginEditBlock() cursor.removeSelectedText() cursor.insertText(html['start tag']) cursor.insertText(text) cursor.insertText(html['end tag']) cursor.endEditBlock() else: cursor = self.textCursor() cursor.insertText(html['start tag']) cursor.insertText(html['end tag'])
def _add_tag_to_formatting(self, tag_name, tags_element): """ Add new formatting tag to the element ``<format>`` if the tag is not present yet. """ available_tags = FormattingTags.get_html_tags() start_tag = '{%s}' % tag_name for tag in available_tags: if tag['start tag'] == start_tag: # Create new formatting tag in openlyrics xml. element = self._add_text_to_element('tag', tags_element) element.set('name', tag_name) element_open = self._add_text_to_element('open', element) element_open.text = etree.CDATA(tag['start html']) # Check if formatting tag contains end tag. Some formatting # tags e.g. {br} has only start tag. If no end tag is present # <close> element has not to be in OpenLyrics xml. if tag['end tag']: element_close = self._add_text_to_element('close', element) element_close.text = etree.CDATA(tag['end html'])
def _process_formatting_tags(self, song_xml, temporary): """ Process the formatting tags from the song and either add missing tags temporary or permanently to the formatting tag list. :param song_xml: The song XML :param temporary: Is the song temporary? """ if not hasattr(song_xml, 'format'): return found_tags = [] for tag in song_xml.format.tags.getchildren(): name = tag.get('name') if name is None: continue start_tag = '{{{name}}}'.format(name=name[:5]) # Some tags have only start tag e.g. {br} end_tag = '{{/{name}}}'.format( name=name[:5]) if hasattr(tag, 'close') else '' openlp_tag = { 'desc': name, 'start tag': start_tag, 'end tag': end_tag, 'start html': tag.open.text, # Some tags have only start html e.g. {br} 'end html': tag.close.text if hasattr(tag, 'close') else '', 'protected': False, # Add 'temporary' key in case the formatting tag should not be saved otherwise it is supposed that # formatting tag is permanent. 'temporary': temporary } found_tags.append(openlp_tag) existing_tag_ids = [ tag['start tag'] for tag in FormattingTags.get_html_tags() ] new_tags = [ tag for tag in found_tags if tag['start tag'] not in existing_tag_ids ] # Do not save an empty list. if new_tags: FormattingTags.add_html_tags(new_tags) if not temporary: custom_tags = [ tag for tag in FormattingTags.get_html_tags() if not tag['protected'] and not tag['temporary'] ] FormattingTags.save_html_tags(custom_tags)
def _add_tag_to_formatting(self, tag_name, tags_element): """ Add new formatting tag to the element ``<format>`` if the tag is not present yet. :param tag_name: The tag_name :param tags_element: Some tag elements """ available_tags = FormattingTags.get_html_tags() start_tag = '{%s}' % tag_name for tag in available_tags: if tag['start tag'] == start_tag: # Create new formatting tag in openlyrics xml. element = self._add_text_to_element('tag', tags_element) element.set('name', tag_name) element_open = self._add_text_to_element('open', element) element_open.text = etree.CDATA(tag['start html']) # Check if formatting tag contains end tag. Some formatting # tags e.g. {br} has only start tag. If no end tag is present # <close> element has not to be in OpenLyrics xml. if tag['end tag']: element_close = self._add_text_to_element('close', element) element_close.text = etree.CDATA(tag['end html'])
def _add_tag_to_formatting(self, tag_name, tags_element): """ Add new formatting tag to the element ``<format>`` if the tag is not present yet. :param tag_name: The tag_name :param tags_element: Some tag elements """ available_tags = FormattingTags.get_html_tags() start_tag = "{%s}" % tag_name for tag in available_tags: if tag["start tag"] == start_tag: # Create new formatting tag in openlyrics xml. element = self._add_text_to_element("tag", tags_element) element.set("name", tag_name) element_open = self._add_text_to_element("open", element) element_open.text = etree.CDATA(tag["start html"]) # Check if formatting tag contains end tag. Some formatting # tags e.g. {br} has only start tag. If no end tag is present # <close> element has not to be in OpenLyrics xml. if tag["end tag"]: element_close = self._add_text_to_element("close", element) element_close.text = etree.CDATA(tag["end html"])
def get_start_tags(raw_text): """ Tests the given text for not closed formatting tags and returns a tuple consisting of three unicode strings:: ('{st}{r}Text text text{/r}{/st}', '{st}{r}', '<strong><span style="-webkit-text-fill-color:red">') The first unicode string is the text, with correct closing tags. The second unicode string are OpenLP's opening formatting tags and the third unicode string the html opening formatting tags. :param raw_text: The text to test. The text must **not** contain html tags, only OpenLP formatting tags are allowed:: {st}{r}Text text text """ raw_tags = [] html_tags = [] for tag in FormattingTags.get_html_tags(): if tag['start tag'] == '{br}': continue if raw_text.count(tag['start tag']) != raw_text.count(tag['end tag']): raw_tags.append((raw_text.find(tag['start tag']), tag['start tag'], tag['end tag'])) html_tags.append( (raw_text.find(tag['start tag']), tag['start html'])) # Sort the lists, so that the tags which were opened first on the first slide (the text we are checking) will be # opened first on the next slide as well. raw_tags.sort(key=lambda tag: tag[0]) html_tags.sort(key=lambda tag: tag[0]) # Create a list with closing tags for the raw_text. end_tags = [] start_tags = [] for tag in raw_tags: start_tags.append(tag[1]) end_tags.append(tag[2]) end_tags.reverse() # Remove the indexes. html_tags = [tag[1] for tag in html_tags] return raw_text + ''.join(end_tags), ''.join(start_tags), ''.join( html_tags)
def get_html_tags_no_user_tags_test(self): """ Test the FormattingTags class' get_html_tags static method. """ with patch('openlp.core.lib.translate') as mocked_translate, \ patch('openlp.core.lib.settings') as mocked_settings, \ patch('openlp.core.lib.formattingtags.json') as mocked_json: # GIVEN: Our mocked modules and functions. mocked_translate.side_effect = lambda module, string_to_translate, comment: string_to_translate mocked_settings.value.return_value = '' mocked_json.load.return_value = [] # WHEN: Get the display tags. FormattingTags.load_tags() old_tags_list = copy.deepcopy(FormattingTags.get_html_tags()) FormattingTags.load_tags() new_tags_list = FormattingTags.get_html_tags() # THEN: Lists should be identical. assert old_tags_list == new_tags_list, 'The formatting tag lists should be identical.'
def test_get_html_tags_no_user_tags(self): """ Test the FormattingTags class' get_html_tags static method. """ with patch('openlp.core.lib.translate') as mocked_translate, \ patch('openlp.core.common.settings') as mocked_settings, \ patch('openlp.core.lib.formattingtags.json') as mocked_json: # GIVEN: Our mocked modules and functions. mocked_translate.side_effect = lambda module, string_to_translate, comment: string_to_translate mocked_settings.value.return_value = '' mocked_json.load.return_value = [] # WHEN: Get the display tags. FormattingTags.load_tags() old_tags_list = copy.deepcopy(FormattingTags.get_html_tags()) FormattingTags.load_tags() new_tags_list = FormattingTags.get_html_tags() # THEN: Lists should be identical. assert old_tags_list == new_tags_list, 'The formatting tag lists should be identical.'
def _process_formatting_tags(self, song_xml, temporary): """ Process the formatting tags from the song and either add missing tags temporary or permanently to the formatting tag list. :param song_xml: The song XML :param temporary: Is the song temporary? """ if not hasattr(song_xml, "format"): return found_tags = [] for tag in song_xml.format.tags.getchildren(): name = tag.get("name") if name is None: continue start_tag = "{%s}" % name[:5] # Some tags have only start tag e.g. {br} end_tag = "{/" + name[:5] + "}" if hasattr(tag, "close") else "" openlp_tag = { "desc": name, "start tag": start_tag, "end tag": end_tag, "start html": tag.open.text, # Some tags have only start html e.g. {br} "end html": tag.close.text if hasattr(tag, "close") else "", "protected": False, # Add 'temporary' key in case the formatting tag should not be saved otherwise it is supposed that # formatting tag is permanent. "temporary": temporary, } found_tags.append(openlp_tag) existing_tag_ids = [tag["start tag"] for tag in FormattingTags.get_html_tags()] new_tags = [tag for tag in found_tags if tag["start tag"] not in existing_tag_ids] # Do not save an empty list. if new_tags: FormattingTags.add_html_tags(new_tags) if not temporary: custom_tags = [ tag for tag in FormattingTags.get_html_tags() if not tag["protected"] and not tag["temporary"] ] FormattingTags.save_html_tags(custom_tags)
def _process_formatting_tags(self, song_xml, temporary): """ Process the formatting tags from the song and either add missing tags temporary or permanently to the formatting tag list. :param song_xml: The song XML :param temporary: Is the song temporary? """ if not hasattr(song_xml, 'format'): return found_tags = [] for tag in song_xml.format.tags.getchildren(): name = tag.get('name') if name is None: continue start_tag = '{%s}' % name[:5] # Some tags have only start tag e.g. {br} end_tag = '{/' + name[:5] + '}' if hasattr(tag, 'close') else '' openlp_tag = { 'desc': name, 'start tag': start_tag, 'end tag': end_tag, 'start html': tag.open.text, # Some tags have only start html e.g. {br} 'end html': tag.close.text if hasattr(tag, 'close') else '', 'protected': False, # Add 'temporary' key in case the formatting tag should not be saved otherwise it is supposed that # formatting tag is permanent. 'temporary': temporary } found_tags.append(openlp_tag) existing_tag_ids = [tag['start tag'] for tag in FormattingTags.get_html_tags()] new_tags = [tag for tag in found_tags if tag['start tag'] not in existing_tag_ids] # Do not save an empty list. if new_tags: FormattingTags.add_html_tags(new_tags) if not temporary: custom_tags = [tag for tag in FormattingTags.get_html_tags() if not tag['protected'] and not tag['temporary']] FormattingTags.save_html_tags(custom_tags)
def __init__(self, manager): self.manager = manager FormattingTags.load_tags()
def save_tags(self): """ Save the new tags if they are valid. """ FormattingTags.save_html_tags(self.custom_tags) FormattingTags.load_tags()
def get_html_tags_with_user_tags_test(self): """ FormattingTags class - test the get_html_tags(), add_html_tags() and remove_html_tag() methods. """ with patch('openlp.core.lib.translate') as mocked_translate, \ patch('openlp.core.lib.settings') as mocked_settings, \ patch('openlp.core.lib.formattingtags.json') as mocked_json: # GIVEN: Our mocked modules and functions. mocked_translate.side_effect = lambda module, string_to_translate: string_to_translate mocked_settings.value.return_value = '' mocked_json.loads.side_effect = [[], [TAG]] # WHEN: Get the display tags. FormattingTags.load_tags() old_tags_list = copy.deepcopy(FormattingTags.get_html_tags()) # WHEN: Add our tag and get the tags again. FormattingTags.load_tags() FormattingTags.add_html_tags([TAG]) new_tags_list = copy.deepcopy(FormattingTags.get_html_tags()) # THEN: Lists should not be identical. assert old_tags_list != new_tags_list, 'The lists should be different.' # THEN: Added tag and last tag should be the same. new_tag = new_tags_list.pop() assert TAG == new_tag, 'Tags should be identical.' # WHEN: Remove the new tag. FormattingTags.remove_html_tag(len(new_tags_list)) # THEN: The lists should now be identical. assert old_tags_list == FormattingTags.get_html_tags(), 'The lists should be identical.'
def test_get_html_tags_with_user_tags(self): """ FormattingTags class - test the get_html_tags(), add_html_tags() and remove_html_tag() methods. """ with patch('openlp.core.lib.translate') as mocked_translate, \ patch('openlp.core.common.settings') as mocked_settings, \ patch('openlp.core.lib.formattingtags.json') as mocked_json: # GIVEN: Our mocked modules and functions. mocked_translate.side_effect = lambda module, string_to_translate: string_to_translate mocked_settings.value.return_value = '' mocked_json.loads.side_effect = [[], [TAG]] # WHEN: Get the display tags. FormattingTags.load_tags() old_tags_list = copy.deepcopy(FormattingTags.get_html_tags()) # WHEN: Add our tag and get the tags again. FormattingTags.load_tags() FormattingTags.add_html_tags([TAG]) new_tags_list = copy.deepcopy(FormattingTags.get_html_tags()) # THEN: Lists should not be identical. assert old_tags_list != new_tags_list, 'The lists should be different.' # THEN: Added tag and last tag should be the same. new_tag = new_tags_list.pop() assert TAG == new_tag, 'Tags should be identical.' # WHEN: Remove the new tag. FormattingTags.remove_html_tag(len(new_tags_list)) # THEN: The lists should now be identical. assert old_tags_list == FormattingTags.get_html_tags(), 'The lists should be identical.'