~sam92/openlp/multiple-songbooks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4

###############################################################################
# OpenLP - Open Source Lyrics Projection                                      #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2016 OpenLP Developers                                   #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it     #
# under the terms of the GNU General Public License as published by the Free  #
# Software Foundation; version 2 of the License.                              #
#                                                                             #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
# more details.                                                               #
#                                                                             #
# You should have received a copy of the GNU General Public License along     #
# with this program; if not, write to the Free Software Foundation, Inc., 59  #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
###############################################################################
"""
The :mod:`formattingtagform` provides an Tag Edit facility. The Base set are protected and included each time loaded.
Custom tags can be defined and saved. The Custom Tag arrays are saved in a json string so QSettings works on them.
Base Tags cannot be changed.
"""

from PyQt5 import QtCore, QtWidgets

from openlp.core.common import translate
from openlp.core.lib import FormattingTags
from openlp.core.ui.formattingtagdialog import Ui_FormattingTagDialog
from openlp.core.ui.formattingtagcontroller import FormattingTagController


class EditColumn(object):
    """
    Hides the magic numbers for the table columns
    """
    Description = 0
    Tag = 1
    StartHtml = 2
    EndHtml = 3


class FormattingTagForm(QtWidgets.QDialog, Ui_FormattingTagDialog, FormattingTagController):
    """
    The :class:`FormattingTagForm` manages the settings tab .
    """
    def __init__(self, parent):
        """
        Constructor
        """
        super(FormattingTagForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint
                | QtCore.Qt.WindowTitleHint)
        self.setupUi(self)
        self._setup()

    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 exec(self):
        """
        Load Display and set field state.
        """
        # Create initial copy from master
        self._reloadTable()
        return QtWidgets.QDialog.exec(self)

    def on_row_selected(self):
        """
        Table Row selected so display items and set field state.
        """
        self.delete_button.setEnabled(True)

    def on_new_clicked(self):
        """
        Add a new tag to edit list and select it for editing.
        """
        new_row = self.tag_table_widget.rowCount()
        self.tag_table_widget.insertRow(new_row)
        self.tag_table_widget.setItem(new_row, 0, QtWidgets.QTableWidgetItem(translate('OpenLP.FormattingTagForm',
                                                                                       'New Tag %d' % new_row)))
        self.tag_table_widget.setItem(new_row, 1, QtWidgets.QTableWidgetItem('n%d' % new_row))
        self.tag_table_widget.setItem(new_row, 2,
                                      QtWidgets.QTableWidgetItem(translate('OpenLP.FormattingTagForm', '<HTML here>')))
        self.tag_table_widget.setItem(new_row, 3, QtWidgets.QTableWidgetItem(''))
        self.tag_table_widget.resizeRowsToContents()
        self.tag_table_widget.scrollToBottom()
        self.tag_table_widget.selectRow(new_row)

    def on_delete_clicked(self):
        """
        Delete selected custom row.
        """
        selected = self.tag_table_widget.currentRow()
        if selected != -1:
            self.is_deleting = True
            self.tag_table_widget.removeRow(selected)

    def accept(self):
        """
        Update Custom Tag details if not duplicate and save the data.
        """
        count = 0
        self.services.pre_save()
        while count < self.tag_table_widget.rowCount():
            error = self.services.validate_for_save(self.tag_table_widget.item(count, 0).text(),
                                                    self.tag_table_widget.item(count, 1).text(),
                                                    self.tag_table_widget.item(count, 2).text(),
                                                    self.tag_table_widget.item(count, 3).text())
            if error:
                QtWidgets.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), error,
                                              QtWidgets.QMessageBox.Ok)
                self.tag_table_widget.selectRow(count)
                return
            count += 1
        self.services.save_tags()
        QtWidgets.QDialog.accept(self)

    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, QtWidgets.QTableWidgetItem(html['desc']))
                self.tag_table_widget_read.setItem(line, 1, QtWidgets.QTableWidgetItem(self._strip(html['start tag'])))
                self.tag_table_widget_read.setItem(line, 2, QtWidgets.QTableWidgetItem(html['start html']))
                self.tag_table_widget_read.setItem(line, 3, QtWidgets.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, QtWidgets.QTableWidgetItem(html['desc']))
                self.tag_table_widget.setItem(line, 1, QtWidgets.QTableWidgetItem(self._strip(html['start tag'])))
                self.tag_table_widget.setItem(line, 2, QtWidgets.QTableWidgetItem(html['start html']))
                self.tag_table_widget.setItem(line, 3, QtWidgets.QTableWidgetItem(html['end html']))
                self.tag_table_widget.resizeRowsToContents()
                # Permanent (persistent) tags do not have this key
                html['temporary'] = False
        self.reloading = 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.
        """
        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()