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.'
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 _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 _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_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 _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_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_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 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 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. :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)