diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 4322eb29a..b798759f1 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -195,33 +195,20 @@ class AdvancedTab(SettingsTab): # Service Item Slide Limits self.slideGroupBox = QtGui.QGroupBox(self.rightColumn) self.slideGroupBox.setObjectName(u'slideGroupBox') - self.slideLayout = QtGui.QFormLayout(self.slideGroupBox) - self.slideLayout.setLabelAlignment( - QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) - self.slideLayout.setFormAlignment( - QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) + self.slideLayout = QtGui.QVBoxLayout(self.slideGroupBox) self.slideLayout.setObjectName(u'slideLayout') + self.slideLabel = QtGui.QLabel(self.slideGroupBox) + self.slideLabel.setWordWrap(True) + self.slideLayout.addWidget(self.slideLabel) self.endSlideRadioButton = QtGui.QRadioButton(self.slideGroupBox) self.endSlideRadioButton.setObjectName(u'endSlideRadioButton') - self.endSlideLabel = QtGui.QLabel(self.slideGroupBox) - self.endSlideLabel.setWordWrap(True) - self.endSlideLabel.setObjectName(u'endSlideLabel') - self.slideLayout.addRow(self.endSlideRadioButton, self.endSlideLabel) + self.slideLayout.addWidget(self.endSlideRadioButton) self.wrapSlideRadioButton = QtGui.QRadioButton(self.slideGroupBox) self.wrapSlideRadioButton.setObjectName(u'wrapSlideRadioButton') - self.wrapSlideLabel = QtGui.QLabel(self.slideGroupBox) - self.wrapSlideLabel.setWordWrap(True) - self.wrapSlideLabel.setObjectName(u'wrapSlideLabel') - self.slideLayout.addRow(self.wrapSlideRadioButton, - self.wrapSlideLabel) + self.slideLayout.addWidget(self.wrapSlideRadioButton) self.nextItemRadioButton = QtGui.QRadioButton(self.slideGroupBox) - self.nextItemRadioButton.setChecked(True) self.nextItemRadioButton.setObjectName(u'nextItemRadioButton') - self.nextItemLabel = QtGui.QLabel(self.slideGroupBox) - self.nextItemLabel.setWordWrap(True) - self.nextItemLabel.setObjectName(u'nextItemLabel') - self.slideLayout.addRow(self.nextItemRadioButton, - self.nextItemLabel) + self.slideLayout.addWidget(self.nextItemRadioButton) self.rightLayout.addWidget(self.slideGroupBox) self.x11GroupBox = QtGui.QGroupBox(self.leftColumn) self.x11GroupBox.setObjectName(u'x11GroupBox') @@ -340,22 +327,14 @@ class AdvancedTab(SettingsTab): # Slide Limits self.slideGroupBox.setTitle( translate('OpenLP.GeneralTab', 'Service Item Slide Limits')) + self.slideLabel.setText(translate('OpenLP.GeneralTab', + 'Behavior of next/previous on the last/first slide:')) self.endSlideRadioButton.setText( - translate('OpenLP.GeneralTab', '&End Slide')) - self.endSlideLabel.setText( - translate('OpenLP.GeneralTab', 'Up and down arrow keys ' - 'stop at the top and bottom slides of each Service Item.')) + translate('OpenLP.GeneralTab', '&Remain on Slide')) self.wrapSlideRadioButton.setText( - translate('OpenLP.GeneralTab', '&Wrap Slide')) - self.wrapSlideLabel.setText( - translate('OpenLP.GeneralTab', 'Up and down arrow keys ' - 'wrap around at the top and bottom slides of each Service Item.')) - self.nextItemRadioButton.setText( - translate('OpenLP.GeneralTab', '&Next Item')) - self.nextItemLabel.setText( - translate('OpenLP.GeneralTab', 'Up and down arrow keys ' - 'advance to the next or previous Service Item from the ' - 'top and bottom slides of each Service Item.')) + translate('OpenLP.GeneralTab', '&Wrap around')) + self.nextItemRadioButton.setText(translate('OpenLP.GeneralTab', + '&Move to next/previous service item')) def load(self): """ diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index bc075c3e1..bce3e2def 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -77,7 +77,7 @@ class ServiceManagerList(QtGui.QTreeWidget): if event.buttons() != QtCore.Qt.LeftButton: event.ignore() return - if not self.selectedItems(): + if not self.itemAt(self.mapFromGlobal(QtGui.QCursor.pos())): event.ignore() return drag = QtGui.QDrag(self) @@ -1106,7 +1106,7 @@ class ServiceManager(QtGui.QWidget): self.mainwindow.servicemanagerSettingsSection + u'/service theme', QtCore.QVariant(self.service_theme)) - self.regenerateServiceItems() + self.regenerateServiceItems(True) def themeChange(self): """ @@ -1118,7 +1118,7 @@ class ServiceManager(QtGui.QWidget): self.themeLabel.setVisible(visible) self.themeComboBox.setVisible(visible) - def regenerateServiceItems(self): + def regenerateServiceItems(self, changed=False): """ Rebuild the service list as things have changed and a repaint is the easiest way to do this. @@ -1154,7 +1154,8 @@ class ServiceManager(QtGui.QWidget): repaint=False, selected=item[u'selected']) # Set to False as items may have changed rendering # does not impact the saved song so True may also be valid - self.setModified() + if changed: + self.setModified() # Repaint it once only at the end self.repaintServiceList(-1, -1) Receiver.send_message(u'cursor_normal') @@ -1439,7 +1440,7 @@ class ServiceManager(QtGui.QWidget): theme = None item = self.findServiceItem()[0] self.serviceItems[item][u'service_item'].update_theme(theme) - self.regenerateServiceItems() + self.regenerateServiceItems(True) def _getParentItemData(self, item): parentitem = item.parent() diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 99d0d1bc4..523bf9664 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -291,7 +291,7 @@ class SlideController(Controller): self.toolbar.widgetForAction(self.audioPauseItem).setPopupMode( QtGui.QToolButton.MenuButtonPopup) self.nextTrackItem = create_action(self, u'nextTrackItem', - text=translate('OpenLP.SlideController', 'Next Track'), + text=UiStrings().NextTrack, icon=u':/slides/media_playback_next.png', tooltip=translate( 'OpenLP.SlideController', 'Go to next audio track.'), category=self.category, context=QtCore.Qt.WindowShortcut, diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 72a8b7e3b..421346ba9 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -220,6 +220,8 @@ class ThemeManager(QtGui.QWidget): name = unicode(translate('OpenLP.ThemeManager', '%s (default)')) % new_name self.themeListWidget.item(count).setText(name) + self.deleteToolbarAction.setVisible( + item not in self.themeListWidget.selectedItems()) def changeGlobalFromScreen(self, index=-1): """ diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index e0c264903..2967c0a0d 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -71,24 +71,28 @@ class ThemesTab(SettingsTab): self.SongLevelRadioButton = QtGui.QRadioButton(self.LevelGroupBox) self.SongLevelRadioButton.setObjectName(u'SongLevelRadioButton') self.SongLevelLabel = QtGui.QLabel(self.LevelGroupBox) - self.SongLevelLabel.setWordWrap(True) self.SongLevelLabel.setObjectName(u'SongLevelLabel') self.LevelLayout.addRow(self.SongLevelRadioButton, self.SongLevelLabel) self.ServiceLevelRadioButton = QtGui.QRadioButton(self.LevelGroupBox) self.ServiceLevelRadioButton.setObjectName(u'ServiceLevelRadioButton') self.ServiceLevelLabel = QtGui.QLabel(self.LevelGroupBox) - self.ServiceLevelLabel.setWordWrap(True) self.ServiceLevelLabel.setObjectName(u'ServiceLevelLabel') self.LevelLayout.addRow(self.ServiceLevelRadioButton, self.ServiceLevelLabel) self.GlobalLevelRadioButton = QtGui.QRadioButton(self.LevelGroupBox) - self.GlobalLevelRadioButton.setChecked(True) self.GlobalLevelRadioButton.setObjectName(u'GlobalLevelRadioButton') self.GlobalLevelLabel = QtGui.QLabel(self.LevelGroupBox) - self.GlobalLevelLabel.setWordWrap(True) self.GlobalLevelLabel.setObjectName(u'GlobalLevelLabel') self.LevelLayout.addRow(self.GlobalLevelRadioButton, self.GlobalLevelLabel) + label_top_margin = (self.SongLevelRadioButton.sizeHint().height() - + self.SongLevelLabel.sizeHint().height()) / 2 + for label in [self.SongLevelLabel, self.ServiceLevelLabel, + self.GlobalLevelLabel]: + rect = label.rect() + rect.setTop(rect.top() + label_top_margin) + label.setFrameRect(rect) + label.setWordWrap(True) self.rightLayout.addWidget(self.LevelGroupBox) self.rightLayout.addStretch() QtCore.QObject.connect(self.SongLevelRadioButton, @@ -131,9 +135,8 @@ class ThemesTab(SettingsTab): settings = QtCore.QSettings() settings.beginGroup(self.settingsSection) self.theme_level = settings.value( - u'theme level', QtCore.QVariant(ThemeLevel.Global)).toInt()[0] - self.global_theme = unicode(settings.value( - u'global theme', QtCore.QVariant(u'')).toString()) + u'theme level', ThemeLevel.Song).toInt()[0] + self.global_theme = unicode(settings.value(u'global theme').toString()) settings.endGroup() if self.theme_level == ThemeLevel.Global: self.GlobalLevelRadioButton.setChecked(True) diff --git a/openlp/plugins/bibles/lib/biblestab.py b/openlp/plugins/bibles/lib/biblestab.py index 09d340ad4..353dc265d 100644 --- a/openlp/plugins/bibles/lib/biblestab.py +++ b/openlp/plugins/bibles/lib/biblestab.py @@ -276,11 +276,10 @@ class BiblesTab(SettingsTab): 'end marks may be defined.\nThey have to be separated by a ' 'vertical bar "|".\nPlease clear this edit line to use the ' 'default value.')) - self.languageSelectionGroupBox.setTitle( - translate('BiblesPlugin.BiblesTab', 'Preferred Bookname Language')) + self.languageSelectionGroupBox.setTitle(translate('BiblesPlugin.BiblesTab', + 'Default Search Field Language')) self.languageSelectionLabel.setText(translate('BiblesPlugin.BiblesTab', - 'Choose the language in which the book names of the\nBible should ' - 'be displayed in the Bible search:')) + 'Book name language in search field:')) self.languageSelectionComboBox.setItemText(LanguageSelection.Bible, translate('BiblesPlugin.BiblesTab', 'Bible language')) self.languageSelectionComboBox.setItemText( @@ -288,11 +287,6 @@ class BiblesTab(SettingsTab): translate('BiblesPlugin.BiblesTab', 'Application language')) self.languageSelectionComboBox.setItemText(LanguageSelection.English, translate('BiblesPlugin.BiblesTab', 'English')) - self.languageSelectionComboBox.setToolTip( - translate('BiblesPlugin.BiblesTab', 'Multiple options:\n ' - 'Bible language - the language in which the Bible book names ' - 'were imported\n Application language - the language you have ' - 'chosen for OpenLP\n English - always use English book names')) def onBibleThemeComboBoxChanged(self): self.bible_theme = self.bibleThemeComboBox.currentText() diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py index d7d022a66..6d4c7f9c2 100644 --- a/openlp/plugins/custom/forms/editcustomslideform.py +++ b/openlp/plugins/custom/forms/editcustomslideform.py @@ -72,16 +72,25 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): """ Adds a slide split at the cursor. """ - if self.slideTextEdit.textCursor().columnNumber() != 0: - self.slideTextEdit.insertPlainText(u'\n') - self.slideTextEdit.insertPlainText(u'[===]\n') + self.insertSingleLineTextAtCursor(u'[===]') self.slideTextEdit.setFocus() def onSplitButtonPressed(self): """ Adds a virtual split at cursor. """ - if self.slideTextEdit.textCursor().columnNumber() != 0: - self.slideTextEdit.insertPlainText(u'\n') - self.slideTextEdit.insertPlainText(u'[---]') + self.insertSingleLineTextAtCursor(u'[---]') self.slideTextEdit.setFocus() + + def insertSingleLineTextAtCursor(self, text): + """ + Adds ``text`` in a single line at the cursor position. + """ + full_text = self.slideTextEdit.toPlainText() + position = self.slideTextEdit.textCursor().position() + if position and full_text[position-1] != u'\n': + text = u'\n' + text + if position == len(full_text) or full_text[position] != u'\n': + text += u'\n' + self.slideTextEdit.insertPlainText(text) + diff --git a/openlp/plugins/images/lib/imagetab.py b/openlp/plugins/images/lib/imagetab.py index be54e207c..4e708bd17 100644 --- a/openlp/plugins/images/lib/imagetab.py +++ b/openlp/plugins/images/lib/imagetab.py @@ -53,6 +53,7 @@ class ImageTab(SettingsTab): self.formLayout.addRow(self.colorLayout) self.informationLabel = QtGui.QLabel(self.bgColorGroupBox) self.informationLabel.setObjectName(u'InformationLabel') + self.informationLabel.setWordWrap(True) self.formLayout.addRow(self.informationLabel) self.leftLayout.addWidget(self.bgColorGroupBox) self.leftLayout.addStretch() @@ -69,8 +70,8 @@ class ImageTab(SettingsTab): self.backgroundColorLabel.setText( translate('ImagesPlugin.ImageTab', 'Default Color:')) self.informationLabel.setText( - translate('ImagesPlugin.ImageTab', 'Provides border where image ' - 'is not the correct dimensions for the screen when resized.')) + translate('ImagesPlugin.ImageTab', 'Visible background for images ' + 'with aspect ratio different to screen.')) def onbackgroundColorButtonClicked(self): new_color = QtGui.QColorDialog.getColor( diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py index 747541952..1a1517fd3 100644 --- a/openlp/plugins/songs/forms/editsongdialog.py +++ b/openlp/plugins/songs/forms/editsongdialog.py @@ -69,12 +69,8 @@ class Ui_EditSongDialog(object): self.lyricsLabel.setObjectName(u'lyricsLabel') self.lyricsTabLayout.addWidget(self.lyricsLabel, 2, 0, QtCore.Qt.AlignTop) - self.verseListWidget = QtGui.QTableWidget(self.lyricsTab) - self.verseListWidget.horizontalHeader().setVisible(False) - self.verseListWidget.horizontalHeader().setStretchLastSection(True) - self.verseListWidget.horizontalHeader().setMinimumSectionSize(16) + self.verseListWidget = SingleColumnTableWidget(self.lyricsTab) self.verseListWidget.setAlternatingRowColors(True) - self.verseListWidget.setColumnCount(1) self.verseListWidget.setSelectionBehavior( QtGui.QAbstractItemView.SelectRows) self.verseListWidget.setSelectionMode( @@ -373,3 +369,24 @@ def editSongDialogComboBox(parent, name): comboBox.setInsertPolicy(QtGui.QComboBox.NoInsert) comboBox.setObjectName(name) return comboBox + +class SingleColumnTableWidget(QtGui.QTableWidget): + """ + Class to for a single column table widget to use for the verse table widget. + """ + def __init__(self, parent): + """ + Constrctor + """ + QtGui.QTableWidget.__init__(self, parent) + self.horizontalHeader().setVisible(False) + self.setColumnCount(1) + + def resizeEvent(self, event): + """ + Resize the first column together with the widget. + """ + QtGui.QTableWidget.resizeEvent(self, event) + if self.columnCount(): + self.setColumnWidth(0, event.size().width()) + self.resizeRowsToContents() diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 468139164..330c80110 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -193,19 +193,19 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.song = None self.initialise() self.songTabWidget.setCurrentIndex(0) - self.titleEdit.setText(u'') - self.alternativeEdit.setText(u'') - self.copyrightEdit.setText(u'') - self.verseOrderEdit.setText(u'') - self.commentsEdit.setText(u'') - self.CCLNumberEdit.setText(u'') + self.titleEdit.clear() + self.alternativeEdit.clear() + self.copyrightEdit.clear() + self.verseOrderEdit.clear() + self.commentsEdit.clear() + self.CCLNumberEdit.clear() self.verseListWidget.clear() self.verseListWidget.setRowCount(0) self.authorsListView.clear() self.topicsListView.clear() self.audioListWidget.clear() self.titleEdit.setFocus(QtCore.Qt.OtherFocusReason) - self.songBookNumberEdit.setText(u'') + self.songBookNumberEdit.clear() self.loadAuthors() self.loadTopics() self.loadBooks() @@ -233,10 +233,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.loadMediaFiles() self.song = self.manager.get_object(Song, id) self.titleEdit.setText(self.song.title) - if self.song.alternate_title: - self.alternativeEdit.setText(self.song.alternate_title) - else: - self.alternativeEdit.setText(u'') + self.alternativeEdit.setText( + self.song.alternate_title if self.song.alternate_title else u'') if self.song.song_book_id != 0: book_name = self.manager.get_object(Book, self.song.song_book_id) find_and_set_in_combo_box( @@ -244,24 +242,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): if self.song.theme_name: find_and_set_in_combo_box( self.themeComboBox, unicode(self.song.theme_name)) - if self.song.copyright: - self.copyrightEdit.setText(self.song.copyright) - else: - self.copyrightEdit.setText(u'') - self.verseListWidget.clear() - self.verseListWidget.setRowCount(0) - if self.song.comments: - self.commentsEdit.setPlainText(self.song.comments) - else: - self.commentsEdit.setPlainText(u'') - if self.song.ccli_number: - self.CCLNumberEdit.setText(self.song.ccli_number) - else: - self.CCLNumberEdit.setText(u'') - if self.song.song_number: - self.songBookNumberEdit.setText(self.song.song_number) - else: - self.songBookNumberEdit.setText(u'') + self.copyrightEdit.setText( + self.song.copyright if self.song.copyright else u'') + self.commentsEdit.setPlainText( + self.song.comments if self.song.comments else u'') + self.CCLNumberEdit.setText( + self.song.ccli_number if self.song.ccli_number else u'') + self.songBookNumberEdit.setText( + self.song.song_number if self.song.song_number else u'') # lazy xml migration for now self.verseListWidget.clear() self.verseListWidget.setRowCount(0) @@ -355,7 +343,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): row_def = u'%s%s' % (verse_tag, verse_def[1:]) row_label.append(row_def) self.verseListWidget.setVerticalHeaderLabels(row_label) - self.verseListWidget.setColumnWidth(0, self.width) self.verseListWidget.resizeRowsToContents() self.verseListWidget.repaint() diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py index f4c9e6cb3..1e7bf4375 100644 --- a/openlp/plugins/songs/forms/editverseform.py +++ b/openlp/plugins/songs/forms/editverseform.py @@ -75,10 +75,14 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): self.verseTextEdit.setFocus() def onSplitButtonClicked(self): - verse_type_index = self.verseTypeComboBox.currentIndex() - if self.verseTextEdit.textCursor().columnNumber() != 0: - self.verseTextEdit.insertPlainText(u'\n') - self.verseTextEdit.insertPlainText(u'[---]') + text = self.verseTextEdit.toPlainText() + position = self.verseTextEdit.textCursor().position() + insert_string = u'[---]' + if position and text[position-1] != u'\n': + insert_string = u'\n' + insert_string + if position == len(text) or text[position] != u'\n': + insert_string += u'\n' + self.verseTextEdit.insertPlainText(insert_string) self.verseTextEdit.setFocus() def onInsertButtonClicked(self): @@ -113,8 +117,7 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): verse_num = int(match.group(2)) except ValueError: verse_num = 1 - verse_type_index = VerseType.from_loose_input(verse_tag, None) - if verse_type_index is not None: + if VerseType.from_loose_input(verse_tag, False): self.verseNumberBox.setValue(verse_num) def onCursorPositionChanged(self): diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 5aa35ffae..e04b1c5a2 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -326,7 +326,7 @@ def clean_song(manager, song): # Rebuild the verse order, to convert translated verse tags, which might # have been added prior to 1.9.5. if song.verse_order: - order = song.verse_order.strip().split() + order = CONTROL_CHARS.sub(u'', song.verse_order).strip().split() else: order = [] new_order = [] @@ -358,6 +358,8 @@ def clean_song(manager, song): author = Author.populate( display_name=name, last_name=u'', first_name=u'') song.authors.append(author) + if song.copyright: + song.copyright = CONTROL_CHARS.sub(u'', song.copyright).strip() from xml import OpenLyrics, SongXML from songstab import SongsTab diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index 977adfb25..ad45ef22e 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -227,9 +227,17 @@ class OpenSongImport(SongImport): verses[verse_tag][verse_num][inst].append(this_line) # done parsing # add verses in original order + verse_joints = {} for (verse_tag, verse_num, inst) in our_verse_order: - verse_def = u'%s%s' % (verse_tag, verse_num) lines = u'\n'.join(verses[verse_tag][verse_num][inst]) + length = 0 + while(length < len(verse_num) and verse_num[length].isnumeric()): + length += 1 + verse_def = u'%s%s' % (verse_tag, verse_num[:length]) + verse_joints[verse_def] = \ + u'%s\n[---]\n%s' % (verse_joints[verse_def], lines) \ + if verse_def in verse_joints else lines + for verse_def, lines in verse_joints.iteritems(): self.addVerse(lines, verse_def) if not self.verses: self.addVerse('') diff --git a/openlp/plugins/songs/lib/songstab.py b/openlp/plugins/songs/lib/songstab.py index 5da2a2a3c..9d6de087f 100644 --- a/openlp/plugins/songs/lib/songstab.py +++ b/openlp/plugins/songs/lib/songstab.py @@ -82,9 +82,8 @@ class SongsTab(SettingsTab): 'Display verses on live tool bar')) self.updateOnEditCheckBox.setText( translate('SongsPlugin.SongsTab', 'Update service from song edit')) - self.addFromServiceCheckBox.setText( - translate('SongsPlugin.SongsTab', - 'Add missing songs when opening service')) + self.addFromServiceCheckBox.setText(translate('SongsPlugin.SongsTab', + 'Import missing songs from service files')) def onSearchAsTypeCheckBoxChanged(self, check_state): self.song_search = False