Meinert Jordan has proposed merging lp:~m2j/openlp/formattingtags into lp:openlp.
Commit message: formatting tag editor reworked Requested reviews: OpenLP Core (openlp-core) For more details, see: https://code.launchpad.net/~m2j/openlp/formattingtags/+merge/140132 I forgot about this branch, and didn't realized, that it was never merged. Now I merged it to the current trunk and did a rework. This branch modifies the formatting tag editor in several ways: - the user gets restricted to valid HTML. - the closing tag is derived from the opening tag - editing happens inline in the table The result looks rather minimalistic, as I would like to shift the editor to the settings dialog. But before I want to discuss this. I'd like to make such a change in a seperated merge request. -- https://code.launchpad.net/~m2j/openlp/formattingtags/+merge/140132 Your team OpenLP Core is requested to review the proposed merge of lp:~m2j/openlp/formattingtags into lp:openlp.
=== modified file 'openlp/core/ui/formattingtagdialog.py' --- openlp/core/ui/formattingtagdialog.py 2012-12-01 07:57:54 +0000 +++ openlp/core/ui/formattingtagdialog.py 2012-12-17 11:31:23 +0000 @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 ############################################################################### # OpenLP - Open Source Lyrics Projection # @@ -30,120 +30,66 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate -from openlp.core.lib.ui import UiStrings, create_button_box +from openlp.core.lib.ui import create_button_box class Ui_FormattingTagDialog(object): - def setupUi(self, formattingTagDialog): - formattingTagDialog.setObjectName(u'formattingTagDialog') - formattingTagDialog.resize(725, 548) - self.listdataGridLayout = QtGui.QGridLayout(formattingTagDialog) - self.listdataGridLayout.setMargin(8) - self.listdataGridLayout.setObjectName(u'listdataGridLayout') - self.tagTableWidget = QtGui.QTableWidget(formattingTagDialog) - self.tagTableWidget.setHorizontalScrollBarPolicy( - QtCore.Qt.ScrollBarAlwaysOff) - self.tagTableWidget.setEditTriggers( - QtGui.QAbstractItemView.NoEditTriggers) - self.tagTableWidget.setAlternatingRowColors(True) - self.tagTableWidget.setSelectionMode( - QtGui.QAbstractItemView.SingleSelection) - self.tagTableWidget.setSelectionBehavior( - QtGui.QAbstractItemView.SelectRows) - self.tagTableWidget.setCornerButtonEnabled(False) - self.tagTableWidget.setObjectName(u'tagTableWidget') - self.tagTableWidget.setColumnCount(4) - self.tagTableWidget.setRowCount(0) - self.tagTableWidget.horizontalHeader().setStretchLastSection(True) - item = QtGui.QTableWidgetItem() - self.tagTableWidget.setHorizontalHeaderItem(0, item) - item = QtGui.QTableWidgetItem() - self.tagTableWidget.setHorizontalHeaderItem(1, item) - item = QtGui.QTableWidgetItem() - self.tagTableWidget.setHorizontalHeaderItem(2, item) - item = QtGui.QTableWidgetItem() - self.tagTableWidget.setHorizontalHeaderItem(3, item) - self.listdataGridLayout.addWidget(self.tagTableWidget, 0, 0, 1, 1) - self.horizontalLayout = QtGui.QHBoxLayout() - self.horizontalLayout.setObjectName(u'horizontalLayout') - spacerItem = QtGui.QSpacerItem(40, 20, - QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout.addItem(spacerItem) - self.deletePushButton = QtGui.QPushButton(formattingTagDialog) - self.deletePushButton.setObjectName(u'deletePushButton') - self.horizontalLayout.addWidget(self.deletePushButton) - self.listdataGridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1) - self.editGroupBox = QtGui.QGroupBox(formattingTagDialog) - self.editGroupBox.setObjectName(u'editGroupBox') - self.dataGridLayout = QtGui.QGridLayout(self.editGroupBox) - self.dataGridLayout.setObjectName(u'dataGridLayout') - self.descriptionLabel = QtGui.QLabel(self.editGroupBox) - self.descriptionLabel.setAlignment(QtCore.Qt.AlignCenter) - self.descriptionLabel.setObjectName(u'descriptionLabel') - self.dataGridLayout.addWidget(self.descriptionLabel, 0, 0, 1, 1) - self.descriptionLineEdit = QtGui.QLineEdit(self.editGroupBox) - self.descriptionLineEdit.setObjectName(u'descriptionLineEdit') - self.dataGridLayout.addWidget(self.descriptionLineEdit, 0, 1, 2, 1) - self.newPushButton = QtGui.QPushButton(self.editGroupBox) - self.newPushButton.setObjectName(u'newPushButton') - self.dataGridLayout.addWidget(self.newPushButton, 0, 2, 2, 1) - self.tagLabel = QtGui.QLabel(self.editGroupBox) - self.tagLabel.setAlignment(QtCore.Qt.AlignCenter) - self.tagLabel.setObjectName(u'tagLabel') - self.dataGridLayout.addWidget(self.tagLabel, 2, 0, 1, 1) - self.tagLineEdit = QtGui.QLineEdit(self.editGroupBox) - self.tagLineEdit.setMaximumSize(QtCore.QSize(50, 16777215)) - self.tagLineEdit.setMaxLength(5) - self.tagLineEdit.setObjectName(u'tagLineEdit') - self.dataGridLayout.addWidget(self.tagLineEdit, 2, 1, 1, 1) - self.startTagLabel = QtGui.QLabel(self.editGroupBox) - self.startTagLabel.setAlignment(QtCore.Qt.AlignCenter) - self.startTagLabel.setObjectName(u'startTagLabel') - self.dataGridLayout.addWidget(self.startTagLabel, 3, 0, 1, 1) - self.startTagLineEdit = QtGui.QLineEdit(self.editGroupBox) - self.startTagLineEdit.setObjectName(u'startTagLineEdit') - self.dataGridLayout.addWidget(self.startTagLineEdit, 3, 1, 1, 1) - self.endTagLabel = QtGui.QLabel(self.editGroupBox) - self.endTagLabel.setAlignment(QtCore.Qt.AlignCenter) - self.endTagLabel.setObjectName(u'endTagLabel') - self.dataGridLayout.addWidget(self.endTagLabel, 4, 0, 1, 1) - self.endTagLineEdit = QtGui.QLineEdit(self.editGroupBox) - self.endTagLineEdit.setObjectName(u'endTagLineEdit') - self.dataGridLayout.addWidget(self.endTagLineEdit, 4, 1, 1, 1) - self.savePushButton = QtGui.QPushButton(self.editGroupBox) - self.savePushButton.setObjectName(u'savePushButton') - self.dataGridLayout.addWidget(self.savePushButton, 4, 2, 1, 1) - self.listdataGridLayout.addWidget(self.editGroupBox, 2, 0, 1, 1) - self.buttonBox = create_button_box(formattingTagDialog, 'buttonBox', - [u'close']) - self.listdataGridLayout.addWidget(self.buttonBox, 3, 0, 1, 1) - - self.retranslateUi(formattingTagDialog) - - def retranslateUi(self, formattingTagDialog): - formattingTagDialog.setWindowTitle(translate( + def setup_ui(self, formatting_tag_dialog): + formatting_tag_dialog.setObjectName(u'formatting_tag_dialog') + formatting_tag_dialog.resize(725, 548) + self.dialog_layout = QtGui.QVBoxLayout(formatting_tag_dialog) + self.dialog_layout.setMargin(8) + self.dialog_layout.setObjectName(u'dialog_layout') + self.tag_table_widget = FormattingTagTableWidget(formatting_tag_dialog) + self.tag_table_widget.setObjectName(u'tagTableWidget') + self.dialog_layout.addWidget(self.tag_table_widget) + self.button_box = create_button_box(formatting_tag_dialog, 'button_box', + [u'cancel', u'save', u'defaults']) + self.save_button = self.button_box.button(QtGui.QDialogButtonBox.Save) + self.save_button.setObjectName(u'save_button') + self.restore_button = self.button_box.button(QtGui.QDialogButtonBox.RestoreDefaults) + self.restore_button.setObjectName(u'restore_button') + self.dialog_layout.addWidget(self.button_box) + + self.retranslate_ui(formatting_tag_dialog) + + def retranslate_ui(self, formatting_tag_dialog): + formatting_tag_dialog.setWindowTitle(translate( 'OpenLP.FormattingTagDialog', 'Configure Formatting Tags')) - self.editGroupBox.setTitle( - translate('OpenLP.FormattingTagDialog', 'Edit Selection')) - self.savePushButton.setText( - translate('OpenLP.FormattingTagDialog', 'Save')) - self.descriptionLabel.setText( - translate('OpenLP.FormattingTagDialog', 'Description')) - self.tagLabel.setText(translate('OpenLP.FormattingTagDialog', 'Tag')) - self.startTagLabel.setText( - translate('OpenLP.FormattingTagDialog', 'Start HTML')) - self.endTagLabel.setText( - translate('OpenLP.FormattingTagDialog', 'End HTML')) - self.deletePushButton.setText(UiStrings().Delete) - self.newPushButton.setText(UiStrings().New) - self.tagTableWidget.horizontalHeaderItem(0).setText( - translate('OpenLP.FormattingTagDialog', 'Description')) - self.tagTableWidget.horizontalHeaderItem(1).setText( + self.tag_table_widget.horizontalHeaderItem(0).setText( translate('OpenLP.FormattingTagDialog', 'Tag')) - self.tagTableWidget.horizontalHeaderItem(2).setText( + self.tag_table_widget.horizontalHeaderItem(1).setText( + translate('OpenLP.FormattingTagDialog', 'Description')) + self.tag_table_widget.horizontalHeaderItem(2).setText( translate('OpenLP.FormattingTagDialog', 'Start HTML')) - self.tagTableWidget.horizontalHeaderItem(3).setText( + self.tag_table_widget.horizontalHeaderItem(3).setText( translate('OpenLP.FormattingTagDialog', 'End HTML')) - self.tagTableWidget.setColumnWidth(0, 120) - self.tagTableWidget.setColumnWidth(1, 80) - self.tagTableWidget.setColumnWidth(2, 330) + +class FormattingTagTableWidget(QtGui.QTableWidget): + """ + Class to for the formatting tag table widget. + """ + def __init__(self, parent): + """ + Constructor + """ + QtGui.QTableWidget.__init__(self, parent) + self.setEditTriggers(QtGui.QAbstractItemView.AllEditTriggers) + self.setAlternatingRowColors(True) + self.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) + self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.verticalHeader().setVisible(False) + self.setColumnCount(4) + for index in range(0, 4): + self.setHorizontalHeaderItem(index, QtGui.QTableWidgetItem()) + + def resizeEvent(self, event): + """ + Resize the start html column to cover remaining space. + """ + QtGui.QTableWidget.resizeEvent(self, event) + if self.columnCount() == 4: + self.resizeColumnsToContents() + self.setColumnWidth(2, event.size().width() - self.columnWidth(0) + - self.columnWidth(1) - self.columnWidth(3)) + self.resizeRowsToContents() === modified file 'openlp/core/ui/formattingtagform.py' --- openlp/core/ui/formattingtagform.py 2012-12-01 07:57:54 +0000 +++ openlp/core/ui/formattingtagform.py 2012-12-17 11:31:23 +0000 @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 ############################################################################### # OpenLP - Open Source Lyrics Projection # @@ -32,10 +32,11 @@ The Custom Tag arrays are saved in a pickle so QSettings works on them. Base Tags cannot be changed. """ +import re +import cgi from PyQt4 import QtCore, QtGui from openlp.core.lib import translate, FormattingTags -from openlp.core.lib.ui import critical_error_message_box from openlp.core.ui.formattingtagdialog import Ui_FormattingTagDialog @@ -48,174 +49,225 @@ Constructor """ QtGui.QDialog.__init__(self, parent) - self.setupUi(self) - QtCore.QObject.connect(self.tagTableWidget, - QtCore.SIGNAL(u'itemSelectionChanged()'),self.onRowSelected) - QtCore.QObject.connect(self.newPushButton, - QtCore.SIGNAL(u'clicked()'), self.onNewClicked) - QtCore.QObject.connect(self.savePushButton, - QtCore.SIGNAL(u'clicked()'), self.onSavedClicked) - QtCore.QObject.connect(self.deletePushButton, - QtCore.SIGNAL(u'clicked()'), self.onDeleteClicked) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'), - self.close) - QtCore.QObject.connect(self.descriptionLineEdit, - QtCore.SIGNAL(u'textEdited(QString)'), self.onTextEdited) - QtCore.QObject.connect(self.tagLineEdit, - QtCore.SIGNAL(u'textEdited(QString)'), self.onTextEdited) - QtCore.QObject.connect(self.startTagLineEdit, - QtCore.SIGNAL(u'textEdited(QString)'), self.onTextEdited) - QtCore.QObject.connect(self.endTagLineEdit, - QtCore.SIGNAL(u'textEdited(QString)'), self.onTextEdited) - # Forces reloading of tags from openlp configuration. + self.setup_ui(self) + QtCore.QObject.connect(self.tag_table_widget, QtCore.SIGNAL(u'currentCellChanged(int, int, int, int)'), + self.on_current_cell_changed) + QtCore.QObject.connect(self.tag_table_widget, QtCore.SIGNAL(u'itemChanged(QTableWidgetItem*)'), + self.on_data_change) + QtCore.QObject.connect(self.restore_button, QtCore.SIGNAL(u'clicked()'), + self.load_tag_table) + QtCore.QObject.connect(self, QtCore.SIGNAL(u'accepted()'), + self.save_tags) + + def exec_(self): + """ + Run the dialog. + """ FormattingTags.load_tags() - - def exec_(self): - """ - Load Display and set field state. - """ - # Create initial copy from master - self._reloadTable() - self.selected = -1 + self.load_tag_table() return QtGui.QDialog.exec_(self) - def onRowSelected(self): - """ - Table Row selected so display items and set field state. - """ - self.savePushButton.setEnabled(False) - self.selected = self.tagTableWidget.currentRow() - html = FormattingTags.get_html_tags()[self.selected] - self.descriptionLineEdit.setText(html[u'desc']) - self.tagLineEdit.setText(self._strip(html[u'start tag'])) - self.startTagLineEdit.setText(html[u'start html']) - self.endTagLineEdit.setText(html[u'end html']) - if html[u'protected']: - self.descriptionLineEdit.setEnabled(False) - self.tagLineEdit.setEnabled(False) - self.startTagLineEdit.setEnabled(False) - self.endTagLineEdit.setEnabled(False) - self.deletePushButton.setEnabled(False) - else: - self.descriptionLineEdit.setEnabled(True) - self.tagLineEdit.setEnabled(True) - self.startTagLineEdit.setEnabled(True) - self.endTagLineEdit.setEnabled(True) - self.deletePushButton.setEnabled(True) - - def onTextEdited(self, text): - """ - Enable the ``savePushButton`` when any of the selected tag's properties - has been changed. - """ - self.savePushButton.setEnabled(True) - - def onNewClicked(self): - """ - Add a new tag to list only if it is not a duplicate. - """ - for html in FormattingTags.get_html_tags(): - if self._strip(html[u'start tag']) == u'n': - critical_error_message_box( - translate('OpenLP.FormattingTagForm', 'Update Error'), + def load_tag_table(self): + """ + Load tags from the Settings into the table widget. + """ + # clear table + self.tag_table_widget.setRowCount(0) + # add tags + tags = FormattingTags.get_html_tags() + for row, tag in enumerate(tags): + self.tag_table_widget.insertRow(row) + item = QtGui.QTableWidgetItem(tag[u'start tag'].strip(u'{}')) + flags = item.flags() + if not tag.get(u'protected'): + item.setData(QtCore.Qt.UserRole, { + u'tag':tag[u'start tag'].strip(u'{}'), + u'html':tag[u'start html'], + u'description':tag[u'desc']}) + else: + flags &= ~QtCore.Qt.ItemIsEditable + item.setFlags(flags) + self.tag_table_widget.setItem(row, 0, item) + item = QtGui.QTableWidgetItem(tag[u'desc']) + item.setToolTip(cgi.escape(tag[u'desc'])) + item.setFlags(flags) + self.tag_table_widget.setItem(row, 1, item) + item = QtGui.QTableWidgetItem(tag[u'start html']) + item.setToolTip(cgi.escape(tag[u'start html'])) + item.setFlags(flags) + self.tag_table_widget.setItem(row, 2, item) + item = QtGui.QTableWidgetItem(tag[u'end html']) + item.setToolTip(cgi.escape(tag[u'end html'])) + item.setFlags(flags & ~QtCore.Qt.ItemIsEditable) + self.tag_table_widget.setItem(row, 3, item) + # add a empty row to allow definition of new tags + row = len(tags) + self.tag_table_widget.insertRow(row) + item = QtGui.QTableWidgetItem(u'') + self.tag_table_widget.setItem(row, 0, item) + flags = item.flags() & ~QtCore.Qt.ItemIsEditable + for column in [1, 2, 3]: + item = QtGui.QTableWidgetItem(u'') + item.setFlags(flags) + self.tag_table_widget.setItem(row, column, item) + self.tag_table_widget.resizeRowsToContents() + self.restore_button.setEnabled(False) + self.save_button.setEnabled(False) + + 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. + """ + # only process for editable rows + pre_row_item = self.tag_table_widget.item(pre_row, 0) + if not pre_row_item or not (pre_row_item.flags() & QtCore.Qt.ItemIsEditable): + return + repair = False + data = self.item_to_data_dict(pre_row_item) + item = self.tag_table_widget.item(pre_row, pre_col) + text = unicode(item.text()) + if pre_col is 0: + # Tag name edited + if text: + for row in range(self.tag_table_widget.rowCount()): + counting_item = self.tag_table_widget.item(row, 0) + if row != pre_row and counting_item and counting_item.text() == text: + answer = QtGui.QMessageBox.warning(self, + translate('OpenLP.FormattingTagForm', 'Validation Error'), + translate('OpenLP.FormattingTagForm', + 'Tag %s is already defined. Please pick a different one.' % text), + QtGui.QMessageBox.Discard|QtGui.QMessageBox.Ok) + if answer == QtGui.QMessageBox.Discard: + item.setText(data.get(u'tag')) + else: + repair = True + break + if not repair: + data[u'tag'] = text + data.setdefault(u'description', u'') + data.setdefault(u'html', u'') + pre_row_item.setData(QtCore.Qt.UserRole, data) + flags = self.tag_table_widget.item(pre_row, 1).flags() + if not (flags & QtCore.Qt.ItemIsEditable): + # if description cell is read only, the user is adding a new tag. + # So we add another empty row and enable editing for description and html. + new_row = self.tag_table_widget.rowCount() + self.tag_table_widget.insertRow(new_row) + for column in range(4): + new_item = QtGui.QTableWidgetItem(u'') + if column != 0: + new_item.setFlags(flags) + self.tag_table_widget.setItem(new_row, column, new_item) + for column in [1, 2]: + self.tag_table_widget.item(pre_row, column).setFlags(item.flags()) + # trigger edit as editing might have been enabled after selecting + cur_item = self.tag_table_widget.item(cur_row, cur_col) + if cur_item and cur_item.flags() & ~QtCore.Qt.ItemIsEditable: + self.tag_table_widget.editItem(cur_item) + self.tag_table_widget.resizeRowsToContents() + else: + answer = None + if self.tag_table_widget.item(pre_row, 1).text() \ + or self.tag_table_widget.item(pre_row, 2).text(): + answer = QtGui.QMessageBox.warning(self, + translate('OpenLP.FormattingTagForm', 'Validation Error'), + translate('OpenLP.FormattingTagForm', + 'No tag name defined. Do you want to delete the whole tag?'), + QtGui.QMessageBox.Yes|QtGui.QMessageBox.Discard|QtGui.QMessageBox.Cancel) + if answer == QtGui.QMessageBox.Discard: + item.setText(data.get(u'tag')) + if answer == QtGui.QMessageBox.Cancel: + repair = True + elif pre_row < self.tag_table_widget.rowCount() - 1: + self.tag_table_widget.removeRow(pre_row) + elif pre_col is 1: + # Description edited + data[u'description'] = text + pre_row_item.setData(QtCore.Qt.UserRole, data) + elif pre_col is 2: + # HTML edited + end_html = self.start_html_to_end_html(text) + if end_html is not None: + item.setToolTip(cgi.escape(text)) + if self.tag_table_widget.item(pre_row, 3) is None: + self.tag_table_widget.setItem(pre_row, 3, QtGui.QTableWidgetItem(end_html)) + else: + self.tag_table_widget.item(pre_row, 3).setText(end_html) + self.tag_table_widget.item(pre_row, 3).setToolTip(cgi.escape(end_html)) + data[u'html'] = text + pre_row_item.setData(QtCore.Qt.UserRole, data) + self.tag_table_widget.resizeRowsToContents() + elif QtGui.QMessageBox.question(self, + translate('OpenLP.FormattingTagForm', 'Validation Error'), translate('OpenLP.FormattingTagForm', - 'Tag "n" already defined.')) - return - # Add new tag to list - tag = { - u'desc': translate('OpenLP.FormattingTagForm', 'New Tag'), - u'start tag': u'{n}', - u'start html': translate('OpenLP.FormattingTagForm', '<HTML here>'), - u'end tag': u'{/n}', - u'end html': translate('OpenLP.FormattingTagForm', '</and here>'), - u'protected': False, - u'temporary': False - } - FormattingTags.add_html_tags([tag]) - FormattingTags.save_html_tags() - self._reloadTable() - # Highlight new row - self.tagTableWidget.selectRow(self.tagTableWidget.rowCount() - 1) - self.onRowSelected() - self.tagTableWidget.scrollToBottom() - #self.savePushButton.setEnabled(False) - - def onDeleteClicked(self): - """ - Delete selected custom tag. - """ - if self.selected != -1: - FormattingTags.remove_html_tag(self.selected) - # As the first items are protected we should not have to take care - # of negative indexes causing tracebacks. - self.tagTableWidget.selectRow(self.selected - 1) - self.selected = -1 - FormattingTags.save_html_tags() - self._reloadTable() - - def onSavedClicked(self): - """ - Update Custom Tag details if not duplicate and save the data. - """ - html_expands = FormattingTags.get_html_tags() - if self.selected != -1: - html = html_expands[self.selected] - tag = unicode(self.tagLineEdit.text()) - for linenumber, html1 in enumerate(html_expands): - if self._strip(html1[u'start tag']) == tag and \ - linenumber != self.selected: - critical_error_message_box( - translate('OpenLP.FormattingTagForm', 'Update Error'), - unicode(translate('OpenLP.FormattingTagForm', - 'Tag %s already defined.')) % tag) - return - html[u'desc'] = unicode(self.descriptionLineEdit.text()) - html[u'start html'] = unicode(self.startTagLineEdit.text()) - html[u'end html'] = unicode(self.endTagLineEdit.text()) - html[u'start tag'] = u'{%s}' % tag - html[u'end tag'] = u'{/%s}' % tag - # Keep temporary tags when the user changes one. - html[u'temporary'] = False - self.selected = -1 - FormattingTags.save_html_tags() - self._reloadTable() - - def _reloadTable(self): - """ - Reset List for loading. - """ - self.tagTableWidget.clearContents() - self.tagTableWidget.setRowCount(0) - self.newPushButton.setEnabled(True) - self.savePushButton.setEnabled(False) - self.deletePushButton.setEnabled(False) - for linenumber, html in enumerate(FormattingTags.get_html_tags()): - self.tagTableWidget.setRowCount(self.tagTableWidget.rowCount() + 1) - self.tagTableWidget.setItem(linenumber, 0, - QtGui.QTableWidgetItem(html[u'desc'])) - self.tagTableWidget.setItem(linenumber, 1, - QtGui.QTableWidgetItem(self._strip(html[u'start tag']))) - self.tagTableWidget.setItem(linenumber, 2, - QtGui.QTableWidgetItem(html[u'start html'])) - self.tagTableWidget.setItem(linenumber, 3, - QtGui.QTableWidgetItem(html[u'end html'])) - # Permanent (persistent) tags do not have this key. - if u'temporary' not in html: - html[u'temporary'] = False - self.tagTableWidget.resizeRowsToContents() - self.descriptionLineEdit.setText(u'') - self.tagLineEdit.setText(u'') - self.startTagLineEdit.setText(u'') - self.endTagLineEdit.setText(u'') - self.descriptionLineEdit.setEnabled(False) - self.tagLineEdit.setEnabled(False) - self.startTagLineEdit.setEnabled(False) - self.endTagLineEdit.setEnabled(False) - - def _strip(self, tag): - """ - Remove tag wrappers for editing. - """ - tag = tag.replace(u'{', u'') - tag = tag.replace(u'}', u'') - return tag + 'The entered HTML is not valid. Please enter valid HTML.'), + QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) == QtGui.QMessageBox.Cancel: + item.setText(data.get(u'html')) + else: + repair = True + if repair: + self.tag_table_widget.setCurrentItem(item, QtGui.QItemSelectionModel.ClearAndSelect) + widget = self.tag_table_widget.cellWidget(pre_row, pre_col) + if widget: + widget.setFocus() + + def on_data_change(self, item): + self.restore_button.setEnabled(True) + self.save_button.setEnabled(True) + + def start_html_to_end_html(self, start_html): + """ + Return the end HTML for a given start HTML or None if invalid. + """ + end_tags = [] + tag_regex = re.compile(r'<(?:(?P<close>/(?=[^\s/>]+>))?' + r'(?P<tag>[^\s/!\?>]+)(?:\s+[^\s=]+="[^"]*")*\s*(?P<empty>/)?' + r'|(?P<cdata>!\[CDATA\[(?:(?!\]\]>).)*\]\])' + r'|(?P<procinst>\?(?:(?!\?>).)*\?)' + r'|(?P<comment>!--(?:(?!-->).)*--))>', re.UNICODE) + code_regex = re.compile(r'^(?:[^<>]*%s)*[^<>]*$' % tag_regex.pattern) + match = code_regex.match(start_html) + if match: + match = tag_regex.search(start_html) + while match: + if match.group(u'tag'): + tag = match.group(u'tag').lower() + if match.group(u'close'): + if match.group(u'empty') or end_tags.pop() != tag: + return + elif not match.group(u'empty'): + end_tags.append(tag) + match = tag_regex.search(start_html, match.end()) + return u''.join(map(lambda tag: u'</%s>' % tag, reversed(end_tags))) + + def item_to_data_dict(self, item): + """ + Reads the data from a QTableWidgetItem and returns a dict with unicode keys and values. + """ + data = {} + for key, value in item.data(QtCore.Qt.UserRole).toMap().items(): + data[unicode(key)] = unicode(value.toString()) + return data + + def save_tags(self): + """ + Saves the table to the settings. + """ + for id, tag in enumerate(FormattingTags.get_html_tags()): + if not tag.get(u'protected'): + FormattingTags.remove_html_tag(id) + tags = [] + for row in range(self.tag_table_widget.rowCount()): + if self.tag_table_widget.item(row, 0).flags() & QtCore.Qt.ItemIsEditable: + data = self.item_to_data_dict(self.tag_table_widget.item(row, 0)) + if data.get(u'tag'): + tags.append({ + u'desc': data[u'description'], + u'start tag': u'{%s}' % data[u'tag'], + u'start html': data[u'html'], + u'end tag': u'{/%s}' % data[u'tag'], + u'end html': self.start_html_to_end_html(data[u'html']), + u'protected': False, + u'temporary': False}) + FormattingTags.add_html_tags(tags) + FormattingTags.save_html_tags()
_______________________________________________ Mailing list: https://launchpad.net/~openlp-core Post to : openlp-core@lists.launchpad.net Unsubscribe : https://launchpad.net/~openlp-core More help : https://help.launchpad.net/ListHelp