diff --git a/documentation/manual/source/faq.rst b/documentation/manual/source/faq.rst index 39c21aece..abba7a553 100644 --- a/documentation/manual/source/faq.rst +++ b/documentation/manual/source/faq.rst @@ -5,32 +5,6 @@ Frequently Asked Questions General Questions ================= -What is OpenLP? ---------------- - - -OpenLP stands for "Open source Lyric Projection" and is presentation software -developed for Churches to provide a single easy to use interface for the -projection needs of a typical act of Worship. First created in 2004, it has -steadily grown in features and maturity such that is it now a mainstay in -hundreds of churches around the world. - -It can hold a searchable database of song lyrics and Bible verses allowing them -to be projected instantly or saved in a pre-prepared order of service file. -Themes allow song backgrounds to be changed instantly. PowerPoint presentations, -videos and audio files can be run from within the program removing the need to -switch between different programs. Alert messages can be displayed so the -Nursery or Car park stewards can notify the congregation easily. Remote -capability allows the worship leader to change songs, or for alert messages to -be sent from anywhere on the network, even via a phone. - -Being free, this software can be installed on as many computers as required, -even on the home computers of worship leaders without additional cost. Compared -to the expensive site licenses or restrictions of commercial software we believe -OpenLP cannot be beaten for value. Still in active development by a growing team -of enthusiastic developers, features are being added all the time, meaning the -software just improves all the time. - When is the release date for OpenLP 2.0? ---------------------------------------- @@ -67,7 +41,7 @@ A variety of places! it, then perhaps review the software or ask others to review it. What operating systems will OpenLP 2.0 support? -=============================================== +----------------------------------------------- OpenLP 2.0 is designed to be cross platform. Currently it has been known to run on Windows (XP, Vista, 7), Linux (Ubuntu/Kubuntu, Fedora), FreeBSD & Mac OSX. @@ -377,7 +351,7 @@ please post a new bug report. ``bugs (at) openlp.org``. What information should I include in a bug report? -================================================== +-------------------------------------------------- Since OpenLP 1.9.4, there is a bug report dialog which automatically opens when OpenLP hits a serious bug. However, this doesn't appear all the time, and in @@ -595,4 +569,4 @@ First of all check it isn't on the `Feature Requests `_ -and post the idea there. \ No newline at end of file +and post the idea there. diff --git a/documentation/manual/source/introduction.rst b/documentation/manual/source/introduction.rst index 05ddcb1e3..b14ef3944 100644 --- a/documentation/manual/source/introduction.rst +++ b/documentation/manual/source/introduction.rst @@ -8,7 +8,7 @@ About OpenLP stands for "Open Source Lyrics Projection" and is presentation software developed for churches to provide a single easy to use interface for the projection needs of a typical worship service. First created in 2004, it has -steadily grown in features and maturity such that is it now a mainstay in +steadily grown in features and maturity such that it is now a mainstay in hundreds of churches around the world. OpenLP has searchable databases of songs and Bible verses allowing them to be @@ -40,5 +40,4 @@ to charge for the software, and that you have to distribute the source code as well. You can find a copy of the GNU General Public License from the Help menu -selecting about OpenLP or on-line at: -``_. +selecting about OpenLP or `view the license on-line `_. diff --git a/documentation/manual/source/themes.rst b/documentation/manual/source/themes.rst index b689cb1a8..7e041cea2 100644 --- a/documentation/manual/source/themes.rst +++ b/documentation/manual/source/themes.rst @@ -1,3 +1,5 @@ +.. _themes: + ====== Themes ====== diff --git a/documentation/manual/source/troubleshooting.rst b/documentation/manual/source/troubleshooting.rst index 10cb4708d..1d200ed8e 100644 --- a/documentation/manual/source/troubleshooting.rst +++ b/documentation/manual/source/troubleshooting.rst @@ -126,7 +126,7 @@ I can not see the book, chapter, and verse when I display scripture The book, chapter, and verse should be displayed when you display scripture. If you can not see this your theme probably has the text size too small for the -info to be seen. See the section of the manual on themes if you need more info +info to be seen. See the section of the manual on :ref:`themes` if you need more info on text sizes in themes. I am running Mac OS X and I do not have a presentations plugin @@ -173,4 +173,5 @@ I chose to use a web Bible but it did not download the entire Bible Due to copyright restrictions OpenLP cannot download an entire Bible. It can only download the section you search for. If you do not have an internet connection where you intend to use OpenLP you will need another scripture -source. For more information about acquiring bibles please see :ref:`bibleimporter`. +source. For more information about acquiring Bibles please see :ref:`bibleimporter`. + diff --git a/openlp.pyw b/openlp.pyw index 57dbcb698..5c3b8ca77 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -116,7 +116,7 @@ class OpenLP(QtGui.QApplication): self.processEvents() # start the main app window self.mainWindow = MainWindow(screens, self.clipboard(), - self.arguments()) + self.arguments()) self.mainWindow.show() if show_splash: # now kill the splashscreen diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index e62cb3e44..491f3e652 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -166,58 +166,6 @@ def build_icon(icon): QtGui.QIcon.Normal, QtGui.QIcon.Off) return button_icon -def context_menu_action(base, icon, text, slot, shortcuts=None): - """ - Utility method to help build context menus for plugins - - ``base`` - The parent menu to add this menu item to - - ``icon`` - An icon for this action - - ``text`` - The text to display for this action - - ``slot`` - The code to run when this action is triggered - """ - action = QtGui.QAction(text, base) - if icon: - action.setIcon(build_icon(icon)) - QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), slot) - if shortcuts: - action.setShortcuts(shortcuts) - return action - -def context_menu(base, icon, text): - """ - Utility method to help build context menus for plugins - - ``base`` - The parent object to add this menu to - - ``icon`` - An icon for this menu - - ``text`` - The text to display for this menu - """ - action = QtGui.QMenu(text, base) - action.setIcon(build_icon(icon)) - return action - -def context_menu_separator(base): - """ - Add a separator to a context menu - - ``base`` - The menu object to add the separator to - """ - action = QtGui.QAction(u'', base) - action.setSeparator(True) - return action - def image_to_byte(image): """ Resize an image to fit on the current screen for the web and returns @@ -343,3 +291,4 @@ from dockwidget import OpenLPDockWidget from renderer import Renderer from rendermanager import RenderManager from mediamanageritem import MediaManagerItem +from openlp.core.utils.actions import ActionList diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index c874c9ff2..2ba235265 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -460,7 +460,7 @@ def build_lyrics_css(item, webkitvers): .lyricsshadow { %s } - """ + """ theme = item.themedata lyricstable = u'' lyrics = u'' @@ -468,8 +468,7 @@ def build_lyrics_css(item, webkitvers): outline = u'' shadow = u'' if theme and item.main: - lyricstable = u'left: %spx; top: %spx;' % \ - (item.main.x(), item.main.y()) + lyricstable = u'left: %spx; top: %spx;' % (item.main.x(), item.main.y()) lyrics = build_lyrics_format_css(theme, item.main.width(), item.main.height()) # For performance reasons we want to show as few DIV's as possible, diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 63132b141..7671064df 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -31,10 +31,10 @@ import os from PyQt4 import QtCore, QtGui -from openlp.core.lib import context_menu_action, context_menu_separator, \ - SettingsManager, OpenLPToolbar, ServiceItem, StringContent, build_icon, \ - translate, Receiver, ListWidgetWithDnD -from openlp.core.lib.ui import UiStrings +from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, \ + StringContent, build_icon, translate, Receiver, ListWidgetWithDnD +from openlp.core.lib.ui import UiStrings, context_menu_action, \ + context_menu_separator log = logging.getLogger(__name__) @@ -260,39 +260,42 @@ class MediaManagerItem(QtGui.QWidget): context_menu_action( self.listView, u':/general/general_edit.png', self.plugin.getString(StringContent.Edit)[u'title'], - self.onEditClick)) + self.onEditClick, context=QtCore.Qt.WidgetShortcut)) self.listView.addAction(context_menu_separator(self.listView)) if self.hasDeleteIcon: self.listView.addAction( context_menu_action( self.listView, u':/general/general_delete.png', self.plugin.getString(StringContent.Delete)[u'title'], - self.onDeleteClick, [QtCore.Qt.Key_Delete])) + self.onDeleteClick, [QtCore.Qt.Key_Delete], + context=QtCore.Qt.WidgetShortcut)) self.listView.addAction(context_menu_separator(self.listView)) self.listView.addAction( context_menu_action( self.listView, u':/general/general_preview.png', self.plugin.getString(StringContent.Preview)[u'title'], - self.onPreviewClick, [QtCore.Qt.Key_Enter])) + self.onPreviewClick, [QtCore.Qt.Key_Enter, + QtCore.Qt.Key_Return], context=QtCore.Qt.WidgetShortcut)) self.listView.addAction( context_menu_action( self.listView, u':/general/general_live.png', self.plugin.getString(StringContent.Live)[u'title'], self.onLiveClick, [QtCore.Qt.ShiftModifier + \ QtCore.Qt.Key_Enter, QtCore.Qt.ShiftModifier + \ - QtCore.Qt.Key_Return])) + QtCore.Qt.Key_Return], context=QtCore.Qt.WidgetShortcut)) self.listView.addAction( context_menu_action( self.listView, u':/general/general_add.png', self.plugin.getString(StringContent.Service)[u'title'], - self.onAddClick, [QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal])) + self.onAddClick, [QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal], + context=QtCore.Qt.WidgetShortcut)) if self.addToServiceItem: self.listView.addAction( context_menu_action( self.listView, u':/general/general_add.png', translate('OpenLP.MediaManagerItem', '&Add to selected Service Item'), - self.onAddEditClick)) + self.onAddEditClick, context=QtCore.Qt.WidgetShortcut)) QtCore.QObject.connect(self.listView, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onClickPressed) diff --git a/openlp/core/lib/searchedit.py b/openlp/core/lib/searchedit.py index 4841d76dc..d32961ef9 100644 --- a/openlp/core/lib/searchedit.py +++ b/openlp/core/lib/searchedit.py @@ -29,6 +29,7 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import build_icon +from openlp.core.lib.ui import icon_action log = logging.getLogger(__name__) @@ -132,7 +133,8 @@ class SearchEdit(QtGui.QLineEdit): menu = QtGui.QMenu(self) first = None for identifier, icon, title in items: - action = QtGui.QAction(build_icon(icon), title, menu) + action = icon_action(menu, u'', icon) + action.setText(title) action.setData(QtCore.QVariant(identifier)) menu.addAction(action) QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'), diff --git a/openlp/core/lib/spelltextedit.py b/openlp/core/lib/spelltextedit.py index 4016dcb09..95befad09 100644 --- a/openlp/core/lib/spelltextedit.py +++ b/openlp/core/lib/spelltextedit.py @@ -23,7 +23,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - +import logging import re try: import enchant @@ -38,20 +38,24 @@ except ImportError: from PyQt4 import QtCore, QtGui from openlp.core.lib import translate, DisplayTags +log = logging.getLogger(__name__) + class SpellTextEdit(QtGui.QPlainTextEdit): """ Spell checking widget based on QPlanTextEdit. """ def __init__(self, *args): + global ENCHANT_AVAILABLE QtGui.QPlainTextEdit.__init__(self, *args) # Default dictionary based on the current locale. if ENCHANT_AVAILABLE: try: self.dictionary = enchant.Dict() + self.highlighter = Highlighter(self.document()) + self.highlighter.spellingDictionary = self.dictionary except DictNotFoundError: - self.dictionary = enchant.Dict(u'en_US') - self.highlighter = Highlighter(self.document()) - self.highlighter.spellingDictionary = self.dictionary + ENCHANT_AVAILABLE = False + log.debug(u'Could not load default dictionary') def mousePressEvent(self, event): """ diff --git a/openlp/core/lib/toolbar.py b/openlp/core/lib/toolbar.py index d5d2fa4f8..d2b37df51 100644 --- a/openlp/core/lib/toolbar.py +++ b/openlp/core/lib/toolbar.py @@ -51,8 +51,7 @@ class OpenLPToolbar(QtGui.QToolBar): log.debug(u'Init done for %s' % parent.__class__.__name__) def addToolbarButton(self, title, icon, tooltip=None, slot=None, - checkable=False, shortcut=0, alternate=0, - context=QtCore.Qt.WidgetShortcut): + checkable=False, shortcuts=None, context=QtCore.Qt.WidgetShortcut): """ A method to help developers easily add a button to the toolbar. @@ -74,16 +73,12 @@ class OpenLPToolbar(QtGui.QToolBar): If *True* the button has two, *off* and *on*, states. Default is *False*, which means the buttons has only one state. - ``shortcut`` - The primary shortcut for this action - - ``alternate`` - The alternate shortcut for this action + ``shortcuts`` + The list of shortcuts for this action ``context`` Specify the context in which this shortcut is valid """ - newAction = None if icon: actionIcon = build_icon(icon) if slot and not checkable: @@ -92,7 +87,7 @@ class OpenLPToolbar(QtGui.QToolBar): newAction = self.addAction(actionIcon, title) self.icons[title] = actionIcon else: - newAction = QtGui.QAction(title, newAction) + newAction = QtGui.QAction(title, self) self.addAction(newAction) QtCore.QObject.connect(newAction, QtCore.SIGNAL(u'triggered()'), slot) @@ -103,8 +98,9 @@ class OpenLPToolbar(QtGui.QToolBar): QtCore.QObject.connect(newAction, QtCore.SIGNAL(u'toggled(bool)'), slot) self.actions[title] = newAction - newAction.setShortcuts([shortcut, alternate]) - newAction.setShortcutContext(context) + if shortcuts is not None: + newAction.setShortcuts(shortcuts) + newAction.setShortcutContext(context) return newAction def addToolbarSeparator(self, handle): diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py index c1a9f8b35..3365b32a0 100644 --- a/openlp/core/lib/ui.py +++ b/openlp/core/lib/ui.py @@ -31,6 +31,7 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import build_icon, Receiver, translate +from openlp.core.utils.actions import ActionList log = logging.getLogger(__name__) @@ -49,14 +50,18 @@ class UiStrings(object): Cancel = translate('OpenLP.Ui', 'Cancel') CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:') CreateService = translate('OpenLP.Ui', 'Create a new service.') + Continuous = translate('OpenLP.Ui', 'Continuous') Default = unicode(translate('OpenLP.Ui', 'Default')) Delete = translate('OpenLP.Ui', '&Delete') + DisplayStyle = translate('OpenLP.Ui', 'Display style:') Edit = translate('OpenLP.Ui', '&Edit') EmptyField = translate('OpenLP.Ui', 'Empty Field') Error = translate('OpenLP.Ui', 'Error') Export = translate('OpenLP.Ui', 'Export') + File = translate('OpenLP.Ui', 'File') FontSizePtUnit = translate('OpenLP.Ui', 'pt', 'Abbreviated font pointsize unit') + Help = translate('OpenLP.Ui', 'Help') Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours') Image = translate('OpenLP.Ui', 'Image') Import = translate('OpenLP.Ui', 'Import') @@ -64,6 +69,7 @@ class UiStrings(object): Live = translate('OpenLP.Ui', 'Live') LiveBGError = translate('OpenLP.Ui', 'Live Background Error') LivePanel = translate('OpenLP.Ui', 'Live Panel') + LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar') Load = translate('OpenLP.Ui', 'Load') Minutes = translate('OpenLP.Ui', 'm', 'The abbreviated unit for minutes') Middle = translate('OpenLP.Ui', 'Middle') @@ -81,6 +87,7 @@ class UiStrings(object): OpenService = translate('OpenLP.Ui', 'Open Service') Preview = translate('OpenLP.Ui', 'Preview') PreviewPanel = translate('OpenLP.Ui', 'Preview Panel') + PreviewToolbar = translate('OpenLP.Ui', 'Preview Toolbar') PrintServiceOrder = translate('OpenLP.Ui', 'Print Service Order') ReplaceBG = translate('OpenLP.Ui', 'Replace Background') ReplaceLiveBG = translate('OpenLP.Ui', 'Replace Live Background') @@ -91,13 +98,19 @@ class UiStrings(object): Search = translate('OpenLP.Ui', 'Search') SelectDelete = translate('OpenLP.Ui', 'You must select an item to delete.') SelectEdit = translate('OpenLP.Ui', 'You must select an item to edit.') + Settings = translate('OpenLP.Ui', 'Settings') SaveService = translate('OpenLP.Ui', 'Save Service') Service = translate('OpenLP.Ui', 'Service') StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s')) Theme = translate('OpenLP.Ui', 'Theme', 'Singular') Themes = translate('OpenLP.Ui', 'Themes', 'Plural') + Tools = translate('OpenLP.Ui', 'Tools') Top = translate('OpenLP.Ui', 'Top') + VersePerSlide = translate('OpenLP.Ui', 'Verse Per Slide') + VersePerLine = translate('OpenLP.Ui', 'Verse Per Line') Version = translate('OpenLP.Ui', 'Version') + View = translate('OpenLP.Ui', 'View') + ViewMode = translate('OpenLP.Ui', 'View Model') def add_welcome_page(parent, image): """ @@ -238,45 +251,128 @@ def create_up_down_push_button_set(parent): QtCore.SIGNAL(u'clicked()'), parent.onDownButtonClicked) return up_button, down_button -def base_action(parent, name): +def base_action(parent, name, category=None): """ Return the most basic action with the object name set. + + ``category`` + The category the action should be listed in the shortcut dialog. If you + not wish, that this action is added to the shortcut dialog, then do not + state any. """ action = QtGui.QAction(parent) action.setObjectName(name) + if category is not None: + action_list = ActionList.get_instance() + action_list.add_action(action, category) return action -def checkable_action(parent, name, checked=None): +def checkable_action(parent, name, checked=None, category=None): """ Return a standard action with the checkable attribute set. """ - action = base_action(parent, name) + action = base_action(parent, name, category) action.setCheckable(True) if checked is not None: action.setChecked(checked) return action -def icon_action(parent, name, icon, checked=None): +def icon_action(parent, name, icon, checked=None, category=None): """ Return a standard action with an icon. """ if checked is not None: - action = checkable_action(parent, name, checked) + action = checkable_action(parent, name, checked, category) else: - action = base_action(parent, name) + action = base_action(parent, name, category) action.setIcon(build_icon(icon)) return action -def shortcut_action(parent, text, shortcuts, function): +def shortcut_action(parent, name, shortcuts, function, icon=None, checked=None, + category=None, context=QtCore.Qt.WindowShortcut): """ Return a shortcut enabled action. """ - action = QtGui.QAction(text, parent) + action = QtGui.QAction(parent) + action.setObjectName(name) + if icon is not None: + action.setIcon(build_icon(icon)) + if checked is not None: + action.setCheckable(True) + action.setChecked(checked) action.setShortcuts(shortcuts) - action.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) + action.setShortcutContext(context) + action_list = ActionList.get_instance() + action_list.add_action(action, category) QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), function) return action +def context_menu_action(base, icon, text, slot, shortcuts=None, category=None, + context=QtCore.Qt.WindowShortcut): + """ + Utility method to help build context menus for plugins + + ``base`` + The parent menu to add this menu item to + + ``icon`` + An icon for this action + + ``text`` + The text to display for this action + + ``slot`` + The code to run when this action is triggered + + ``shortcuts`` + The action's shortcuts. + + ``category`` + The category the shortcut should be listed in the shortcut dialog. If + left to None, then the action will be hidden in the shortcut dialog. + + ``context`` + The context the shortcut is valid. + """ + action = QtGui.QAction(text, base) + if icon: + action.setIcon(build_icon(icon)) + QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), slot) + if shortcuts is not None: + action.setShortcuts(shortcuts) + action.setShortcutContext(context) + action_list = ActionList.get_instance() + action_list.add_action(action) + return action + +def context_menu(base, icon, text): + """ + Utility method to help build context menus for plugins + + ``base`` + The parent object to add this menu to + + ``icon`` + An icon for this menu + + ``text`` + The text to display for this menu + """ + action = QtGui.QMenu(text, base) + action.setIcon(build_icon(icon)) + return action + +def context_menu_separator(base): + """ + Add a separator to a context menu + + ``base`` + The menu object to add the separator to + """ + action = QtGui.QAction(u'', base) + action.setSeparator(True) + return action + def add_widget_completer(cache, widget): """ Adds a text autocompleter to a widget. @@ -315,3 +411,20 @@ def create_valign_combo(form, parent, layout): form.verticalComboBox.addItem(UiStrings.Bottom) verticalLabel.setBuddy(form.verticalComboBox) layout.addRow(verticalLabel, form.verticalComboBox) + +def find_and_set_in_combo_box(combo_box, value_to_find): + """ + Find a string in a combo box and set it as the selected item if present + + ``combo_box`` + The combo box to check for selected items + + ``value_to_find`` + The value to find + """ + index = combo_box.findText(value_to_find, + QtCore.Qt.MatchExactly) + if index == -1: + # Not Found. + index = 0 + combo_box.setCurrentIndex(index) \ No newline at end of file diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 38775d68e..2038e1972 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -33,12 +33,13 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import RenderManager, build_icon, OpenLPDockWidget, \ SettingsManager, PluginManager, Receiver, translate from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \ - icon_action + icon_action, shortcut_action from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \ ThemeManager, SlideController, PluginForm, MediaDockManager, \ ShortcutListForm, DisplayTagForm from openlp.core.utils import AppLocation, add_actions, LanguageManager, \ - ActionList, get_application_version + get_application_version +from openlp.core.utils.actions import ActionList, CategoryOrder log = logging.getLogger(__name__) @@ -161,74 +162,86 @@ class Ui_MainWindow(object): mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.themeManagerDock) # Create the menu items - self.FileNewItem = icon_action(mainWindow, u'FileNewItem', - u':/general/general_new.png') - mainWindow.actionList.add_action(self.FileNewItem, u'File') - self.FileOpenItem = icon_action(mainWindow, u'FileOpenItem', - u':/general/general_open.png') - mainWindow.actionList.add_action(self.FileOpenItem, u'File') - self.FileSaveItem = icon_action(mainWindow, u'FileSaveItem', - u':/general/general_save.png') - mainWindow.actionList.add_action(self.FileSaveItem, u'File') - self.FileSaveAsItem = base_action(mainWindow, u'FileSaveAsItem') - mainWindow.actionList.add_action(self.FileSaveAsItem, u'File') - self.printServiceOrderItem = base_action( - mainWindow, u'printServiceItem') - mainWindow.actionList.add_action( - self.printServiceOrderItem, u'Print Service Order') - self.FileExitItem = icon_action(mainWindow, u'FileExitItem', - u':/system/system_exit.png') - mainWindow.actionList.add_action(self.FileExitItem, u'File') - self.ImportThemeItem = base_action(mainWindow, u'ImportThemeItem') - mainWindow.actionList.add_action(self.ImportThemeItem, u'Import') - self.ImportLanguageItem = base_action(mainWindow, u'ImportLanguageItem') - mainWindow.actionList.add_action(self.ImportLanguageItem, u'Import') - self.ExportThemeItem = base_action(mainWindow, u'ExportThemeItem') - mainWindow.actionList.add_action(self.ExportThemeItem, u'Export') - self.ExportLanguageItem = base_action(mainWindow, u'ExportLanguageItem') - mainWindow.actionList.add_action(self.ExportLanguageItem, u'Export') - self.ViewMediaManagerItem = icon_action(mainWindow, - u'ViewMediaManagerItem', u':/system/system_mediamanager.png', - self.mediaManagerDock.isVisible()) - self.ViewThemeManagerItem = icon_action(mainWindow, - u'ViewThemeManagerItem', u':/system/system_thememanager.png', - self.themeManagerDock.isVisible()) - mainWindow.actionList.add_action(self.ViewMediaManagerItem, u'View') - self.ViewServiceManagerItem = icon_action(mainWindow, - u'ViewServiceManagerItem', u':/system/system_servicemanager.png', - self.serviceManagerDock.isVisible()) - mainWindow.actionList.add_action(self.ViewServiceManagerItem, u'View') - self.ViewPreviewPanel = checkable_action(mainWindow, - u'ViewPreviewPanel', previewVisible) - mainWindow.actionList.add_action(self.ViewPreviewPanel, u'View') - self.ViewLivePanel = checkable_action(mainWindow, u'ViewLivePanel', - liveVisible) - mainWindow.actionList.add_action(self.ViewLivePanel, u'View') - self.ModeDefaultItem = checkable_action(mainWindow, u'ModeDefaultItem') - mainWindow.actionList.add_action(self.ModeDefaultItem, u'View Mode') - self.ModeSetupItem = checkable_action(mainWindow, u'ModeLiveItem') - mainWindow.actionList.add_action(self.ModeSetupItem, u'View Mode') - self.ModeLiveItem = checkable_action(mainWindow, u'ModeLiveItem', True) - mainWindow.actionList.add_action(self.ModeLiveItem, u'View Mode') + action_list = ActionList.get_instance() + action_list.add_category(UiStrings.File, CategoryOrder.standardMenu) + self.FileNewItem = shortcut_action(mainWindow, u'FileNewItem', + [QtGui.QKeySequence(u'Ctrl+N')], + self.ServiceManagerContents.onNewServiceClicked, + u':/general/general_new.png', category=UiStrings.File) + self.FileOpenItem = shortcut_action(mainWindow, u'FileOpenItem', + [QtGui.QKeySequence(u'Ctrl+O')], + self.ServiceManagerContents.onLoadServiceClicked, + u':/general/general_open.png', category=UiStrings.File) + self.FileSaveItem = shortcut_action(mainWindow, u'FileSaveItem', + [QtGui.QKeySequence(u'Ctrl+S')], + self.ServiceManagerContents.saveFile, + u':/general/general_save.png', category=UiStrings.File) + self.FileSaveAsItem = shortcut_action(mainWindow, u'FileSaveAsItem', + [QtGui.QKeySequence(u'Ctrl+Shift+S')], + self.ServiceManagerContents.saveFileAs, category=UiStrings.File) + self.printServiceOrderItem = shortcut_action(mainWindow, + u'printServiceItem', [QtGui.QKeySequence(u'Ctrl+P')], + self.ServiceManagerContents.printServiceOrder, + category=UiStrings.File) + self.FileExitItem = shortcut_action(mainWindow, u'FileExitItem', + [QtGui.QKeySequence(u'Alt+F4')], mainWindow.close, + u':/system/system_exit.png', category=UiStrings.File) + action_list.add_category(UiStrings.Import, CategoryOrder.standardMenu) + self.ImportThemeItem = base_action( + mainWindow, u'ImportThemeItem', UiStrings.Import) + self.ImportLanguageItem = base_action( + mainWindow, u'ImportLanguageItem')#, UiStrings.Import) + action_list.add_category(UiStrings.Export, CategoryOrder.standardMenu) + self.ExportThemeItem = base_action( + mainWindow, u'ExportThemeItem', UiStrings.Export) + self.ExportLanguageItem = base_action( + mainWindow, u'ExportLanguageItem')#, UiStrings.Export) + action_list.add_category(UiStrings.View, CategoryOrder.standardMenu) + self.ViewMediaManagerItem = shortcut_action(mainWindow, + u'ViewMediaManagerItem', [QtGui.QKeySequence(u'F8')], + self.toggleMediaManager, u':/system/system_mediamanager.png', + self.mediaManagerDock.isVisible(), UiStrings.View) + self.ViewThemeManagerItem = shortcut_action(mainWindow, + u'ViewThemeManagerItem', [QtGui.QKeySequence(u'F10')], + self.toggleThemeManager, u':/system/system_thememanager.png', + self.themeManagerDock.isVisible(), UiStrings.View) + self.ViewServiceManagerItem = shortcut_action(mainWindow, + u'ViewServiceManagerItem', [QtGui.QKeySequence(u'F9')], + self.toggleServiceManager, u':/system/system_servicemanager.png', + self.serviceManagerDock.isVisible(), UiStrings.View) + self.ViewPreviewPanel = shortcut_action(mainWindow, + u'ViewPreviewPanel', [QtGui.QKeySequence(u'F11')], + self.setPreviewPanelVisibility, checked=previewVisible, + category=UiStrings.View) + self.ViewLivePanel = shortcut_action(mainWindow, u'ViewLivePanel', + [QtGui.QKeySequence(u'F12')], self.setLivePanelVisibility, + checked=liveVisible, category=UiStrings.View) + action_list.add_category(UiStrings.ViewMode, CategoryOrder.standardMenu) + self.ModeDefaultItem = checkable_action( + mainWindow, u'ModeDefaultItem', category=UiStrings.ViewMode) + self.ModeSetupItem = checkable_action( + mainWindow, u'ModeLiveItem', category=UiStrings.ViewMode) + self.ModeLiveItem = checkable_action( + mainWindow, u'ModeLiveItem', True, UiStrings.ViewMode) self.ModeGroup = QtGui.QActionGroup(mainWindow) self.ModeGroup.addAction(self.ModeDefaultItem) self.ModeGroup.addAction(self.ModeSetupItem) self.ModeGroup.addAction(self.ModeLiveItem) self.ModeDefaultItem.setChecked(True) + action_list.add_category(UiStrings.Tools, CategoryOrder.standardMenu) self.ToolsAddToolItem = icon_action(mainWindow, u'ToolsAddToolItem', - u':/tools/tools_add.png') - mainWindow.actionList.add_action(self.ToolsAddToolItem, u'Tools') + u':/tools/tools_add.png', category=UiStrings.Tools) self.ToolsOpenDataFolder = icon_action(mainWindow, - u'ToolsOpenDataFolder', u':/general/general_open.png') - mainWindow.actionList.add_action(self.ToolsOpenDataFolder, u'Tools') - self.settingsPluginListItem = icon_action(mainWindow, - u'settingsPluginListItem', u':/system/settings_plugin_list.png') - mainWindow.actionList.add_action(self.settingsPluginListItem, - u'Settings') + u'ToolsOpenDataFolder', u':/general/general_open.png', + category=UiStrings.Tools) + action_list.add_category(UiStrings.Settings, CategoryOrder.standardMenu) + self.settingsPluginListItem = shortcut_action(mainWindow, + u'settingsPluginListItem', [QtGui.QKeySequence(u'Alt+F7')], + self.onPluginItemClicked, u':/system/settings_plugin_list.png', + category=UiStrings.Settings) # i18n Language Items self.AutoLanguageItem = checkable_action(mainWindow, u'AutoLanguageItem', LanguageManager.auto_language) - mainWindow.actionList.add_action(self.AutoLanguageItem, u'Settings') self.LanguageGroup = QtGui.QActionGroup(mainWindow) self.LanguageGroup.setExclusive(True) self.LanguageGroup.setObjectName(u'LanguageGroup') @@ -241,24 +254,26 @@ class Ui_MainWindow(object): add_actions(self.LanguageGroup, [languageItem]) self.SettingsShortcutsItem = icon_action(mainWindow, u'SettingsShortcutsItem', - u':/system/system_configure_shortcuts.png') + u':/system/system_configure_shortcuts.png', + category=UiStrings.Settings) self.DisplayTagItem = icon_action(mainWindow, - u'DisplayTagItem', u':/system/tag_editor.png') + u'DisplayTagItem', u':/system/tag_editor.png', + category=UiStrings.Settings) self.SettingsConfigureItem = icon_action(mainWindow, - u'SettingsConfigureItem', u':/system/system_settings.png') - mainWindow.actionList.add_action(self.SettingsShortcutsItem, - u'Settings') + u'SettingsConfigureItem', u':/system/system_settings.png', + category=UiStrings.Settings) + action_list.add_category(UiStrings.Help, CategoryOrder.standardMenu) self.HelpDocumentationItem = icon_action(mainWindow, - u'HelpDocumentationItem', u':/system/system_help_contents.png') + u'HelpDocumentationItem', u':/system/system_help_contents.png', + category=None)#UiStrings.Help) self.HelpDocumentationItem.setEnabled(False) - mainWindow.actionList.add_action(self.HelpDocumentationItem, u'Help') - self.HelpAboutItem = icon_action(mainWindow, u'HelpAboutItem', - u':/system/system_about.png') - mainWindow.actionList.add_action(self.HelpAboutItem, u'Help') - self.HelpOnlineHelpItem = base_action(mainWindow, u'HelpOnlineHelpItem') - mainWindow.actionList.add_action(self.HelpOnlineHelpItem, u'Help') - self.helpWebSiteItem = base_action(mainWindow, u'helpWebSiteItem') - mainWindow.actionList.add_action(self.helpWebSiteItem, u'Help') + self.HelpAboutItem = shortcut_action(mainWindow, u'HelpAboutItem', + [QtGui.QKeySequence(u'Ctrl+F1')], self.onHelpAboutItemClicked, + u':/system/system_about.png', category=UiStrings.Help) + self.HelpOnlineHelpItem = base_action( + mainWindow, u'HelpOnlineHelpItem', category=UiStrings.Help) + self.helpWebSiteItem = base_action( + mainWindow, u'helpWebSiteItem', category=UiStrings.Help) add_actions(self.FileImportMenu, (self.ImportThemeItem, self.ImportLanguageItem)) add_actions(self.FileExportMenu, @@ -294,14 +309,11 @@ class Ui_MainWindow(object): # Connect up some signals and slots QtCore.QObject.connect(self.FileMenu, QtCore.SIGNAL(u'aboutToShow()'), self.updateFileMenu) - QtCore.QObject.connect(self.FileExitItem, - QtCore.SIGNAL(u'triggered()'), mainWindow.close) QtCore.QMetaObject.connectSlotsByName(mainWindow) # Hide the entry, as it does not have any functionality yet. self.ToolsAddToolItem.setVisible(False) self.ImportLanguageItem.setVisible(False) self.ExportLanguageItem.setVisible(False) - self.SettingsShortcutsItem.setVisible(False) self.HelpDocumentationItem.setVisible(False) def retranslateUi(self, mainWindow): @@ -329,36 +341,27 @@ class Ui_MainWindow(object): self.FileNewItem.setText(translate('OpenLP.MainWindow', '&New')) self.FileNewItem.setToolTip(UiStrings.NewService) self.FileNewItem.setStatusTip(UiStrings.CreateService) - self.FileNewItem.setShortcut(translate('OpenLP.MainWindow', 'Ctrl+N')) self.FileOpenItem.setText(translate('OpenLP.MainWindow', '&Open')) self.FileOpenItem.setToolTip(UiStrings.OpenService) self.FileOpenItem.setStatusTip( translate('OpenLP.MainWindow', 'Open an existing service.')) - self.FileOpenItem.setShortcut(translate('OpenLP.MainWindow', 'Ctrl+O')) self.FileSaveItem.setText(translate('OpenLP.MainWindow', '&Save')) self.FileSaveItem.setToolTip(UiStrings.SaveService) self.FileSaveItem.setStatusTip( translate('OpenLP.MainWindow', 'Save the current service to disk.')) - self.FileSaveItem.setShortcut(translate('OpenLP.MainWindow', 'Ctrl+S')) self.FileSaveAsItem.setText( translate('OpenLP.MainWindow', 'Save &As...')) self.FileSaveAsItem.setToolTip( translate('OpenLP.MainWindow', 'Save Service As')) self.FileSaveAsItem.setStatusTip(translate('OpenLP.MainWindow', 'Save the current service under a new name.')) - self.FileSaveAsItem.setShortcut( - translate('OpenLP.MainWindow', 'Ctrl+Shift+S')) self.printServiceOrderItem.setText(UiStrings.PrintServiceOrder) self.printServiceOrderItem.setStatusTip(translate('OpenLP.MainWindow', 'Print the current Service Order.')) - self.printServiceOrderItem.setShortcut( - translate('OpenLP.MainWindow', 'Ctrl+P')) self.FileExitItem.setText( translate('OpenLP.MainWindow', 'E&xit')) self.FileExitItem.setStatusTip( translate('OpenLP.MainWindow', 'Quit OpenLP')) - self.FileExitItem.setShortcut( - translate('OpenLP.MainWindow', 'Alt+F4')) self.ImportThemeItem.setText( translate('OpenLP.MainWindow', '&Theme')) self.ImportLanguageItem.setText( @@ -379,53 +382,39 @@ class Ui_MainWindow(object): translate('OpenLP.MainWindow', 'Toggle Media Manager')) self.ViewMediaManagerItem.setStatusTip(translate('OpenLP.MainWindow', 'Toggle the visibility of the media manager.')) - self.ViewMediaManagerItem.setShortcut( - translate('OpenLP.MainWindow', 'F8')) self.ViewThemeManagerItem.setText( translate('OpenLP.MainWindow', '&Theme Manager')) self.ViewThemeManagerItem.setToolTip( translate('OpenLP.MainWindow', 'Toggle Theme Manager')) self.ViewThemeManagerItem.setStatusTip(translate('OpenLP.MainWindow', 'Toggle the visibility of the theme manager.')) - self.ViewThemeManagerItem.setShortcut( - translate('OpenLP.MainWindow', 'F10')) self.ViewServiceManagerItem.setText( translate('OpenLP.MainWindow', '&Service Manager')) self.ViewServiceManagerItem.setToolTip( translate('OpenLP.MainWindow', 'Toggle Service Manager')) self.ViewServiceManagerItem.setStatusTip(translate('OpenLP.MainWindow', 'Toggle the visibility of the service manager.')) - self.ViewServiceManagerItem.setShortcut( - translate('OpenLP.MainWindow', 'F9')) self.ViewPreviewPanel.setText( translate('OpenLP.MainWindow', '&Preview Panel')) self.ViewPreviewPanel.setToolTip( translate('OpenLP.MainWindow', 'Toggle Preview Panel')) self.ViewPreviewPanel.setStatusTip(translate('OpenLP.MainWindow', 'Toggle the visibility of the preview panel.')) - self.ViewPreviewPanel.setShortcut( - translate('OpenLP.MainWindow', 'F11')) self.ViewLivePanel.setText( translate('OpenLP.MainWindow', '&Live Panel')) self.ViewLivePanel.setToolTip( translate('OpenLP.MainWindow', 'Toggle Live Panel')) self.ViewLivePanel.setStatusTip(translate('OpenLP.MainWindow', 'Toggle the visibility of the live panel.')) - self.ViewLivePanel.setShortcut( - translate('OpenLP.MainWindow', 'F12')) self.settingsPluginListItem.setText(translate('OpenLP.MainWindow', '&Plugin List')) self.settingsPluginListItem.setStatusTip( translate('OpenLP.MainWindow', 'List the Plugins')) - self.settingsPluginListItem.setShortcut( - translate('OpenLP.MainWindow', 'Alt+F7')) self.HelpDocumentationItem.setText( translate('OpenLP.MainWindow', '&User Guide')) self.HelpAboutItem.setText(translate('OpenLP.MainWindow', '&About')) self.HelpAboutItem.setStatusTip( translate('OpenLP.MainWindow', 'More information about OpenLP')) - self.HelpAboutItem.setShortcut( - translate('OpenLP.MainWindow', 'Ctrl+F1')) self.HelpOnlineHelpItem.setText( translate('OpenLP.MainWindow', '&Online Help')) # Uncomment after 1.9.5 beta string freeze @@ -467,8 +456,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ log.info(u'MainWindow loaded') - actionList = ActionList() - def __init__(self, screens, clipboard, arguments): """ This constructor sets up the interface, the various managers, and the @@ -485,7 +472,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.serviceSettingsSection = u'servicemanager' self.songsSettingsSection = u'songs' self.serviceNotSaved = False - self.actionList = ActionList() self.settingsmanager = SettingsManager(screens) self.aboutForm = AboutForm(self) self.settingsForm = SettingsForm(self.screens, self, self) @@ -510,16 +496,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtCore.QObject.connect(self.ExportThemeItem, QtCore.SIGNAL(u'triggered()'), self.themeManagerContents.onExportTheme) - QtCore.QObject.connect(self.ViewMediaManagerItem, - QtCore.SIGNAL(u'triggered(bool)'), self.toggleMediaManager) - QtCore.QObject.connect(self.ViewServiceManagerItem, - QtCore.SIGNAL(u'triggered(bool)'), self.toggleServiceManager) - QtCore.QObject.connect(self.ViewThemeManagerItem, - QtCore.SIGNAL(u'triggered(bool)'), self.toggleThemeManager) - QtCore.QObject.connect(self.ViewPreviewPanel, - QtCore.SIGNAL(u'toggled(bool)'), self.setPreviewPanelVisibility) - QtCore.QObject.connect(self.ViewLivePanel, - QtCore.SIGNAL(u'toggled(bool)'), self.setLivePanelVisibility) QtCore.QObject.connect(self.mediaManagerDock, QtCore.SIGNAL(u'visibilityChanged(bool)'), self.ViewMediaManagerItem.setChecked) @@ -533,32 +509,14 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtCore.SIGNAL(u'triggered()'), self.onHelpWebSiteClicked) QtCore.QObject.connect(self.HelpOnlineHelpItem, QtCore.SIGNAL(u'triggered()'), self.onHelpOnLineHelpClicked) - QtCore.QObject.connect(self.HelpAboutItem, - QtCore.SIGNAL(u'triggered()'), self.onHelpAboutItemClicked) QtCore.QObject.connect(self.ToolsOpenDataFolder, QtCore.SIGNAL(u'triggered()'), self.onToolsOpenDataFolderClicked) - QtCore.QObject.connect(self.settingsPluginListItem, - QtCore.SIGNAL(u'triggered()'), self.onPluginItemClicked) QtCore.QObject.connect(self.DisplayTagItem, QtCore.SIGNAL(u'triggered()'), self.onDisplayTagItemClicked) QtCore.QObject.connect(self.SettingsConfigureItem, QtCore.SIGNAL(u'triggered()'), self.onSettingsConfigureItemClicked) QtCore.QObject.connect(self.SettingsShortcutsItem, QtCore.SIGNAL(u'triggered()'), self.onSettingsShortcutsItemClicked) - QtCore.QObject.connect(self.FileNewItem, QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.onNewServiceClicked) - QtCore.QObject.connect(self.FileOpenItem, - QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.onLoadServiceClicked) - QtCore.QObject.connect(self.FileSaveItem, - QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.saveFile) - QtCore.QObject.connect(self.FileSaveAsItem, - QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.saveFileAs) - QtCore.QObject.connect(self.printServiceOrderItem, - QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.printServiceOrder) # i18n set signals for languages self.LanguageGroup.triggered.connect(LanguageManager.set_language) QtCore.QObject.connect(self.ModeDefaultItem, @@ -781,7 +739,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ Show the shortcuts dialog """ - self.shortcutForm.exec_(self.actionList) + if self.shortcutForm.exec_(): + self.shortcutForm.save() def onModeDefaultItemClicked(self): """ @@ -928,19 +887,16 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): unicode(translate('OpenLP.MainWindow', 'Default Theme: %s')) % theme) - def toggleMediaManager(self, visible): - if self.mediaManagerDock.isVisible() != visible: - self.mediaManagerDock.setVisible(visible) + def toggleMediaManager(self): + self.mediaManagerDock.setVisible(not self.mediaManagerDock.isVisible()) - def toggleServiceManager(self, visible): - if self.serviceManagerDock.isVisible() != visible: - self.serviceManagerDock.setVisible(visible) + def toggleServiceManager(self): + self.serviceManagerDock.setVisible(not self.serviceManagerDock.isVisible()) - def toggleThemeManager(self, visible): - if self.themeManagerDock.isVisible() != visible: - self.themeManagerDock.setVisible(visible) + def toggleThemeManager(self): + self.themeManagerDock.setVisible(not self.themeManagerDock.isVisible()) - def setPreviewPanelVisibility(self, visible): + def setPreviewPanelVisibility(self, visible=None): """ Sets the visibility of the preview panel including saving the setting and updating the menu. @@ -950,12 +906,14 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): True - Visible False - Hidden """ + if visible is None: + visible = self.ViewPreviewPanel.isVisible() self.previewController.panel.setVisible(visible) QtCore.QSettings().setValue(u'user interface/preview panel', QtCore.QVariant(visible)) self.ViewPreviewPanel.setChecked(visible) - def setLivePanelVisibility(self, visible): + def setLivePanelVisibility(self, visible=None): """ Sets the visibility of the live panel including saving the setting and updating the menu. @@ -965,6 +923,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): True - Visible False - Hidden """ + if visible is None: + visible = self.ViewLivePanel.isVisible() self.liveController.panel.setVisible(visible) QtCore.QSettings().setValue(u'user interface/live panel', QtCore.QVariant(visible)) @@ -1022,8 +982,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.FileMenu.addSeparator() for fileId, filename in enumerate(recentFilesToDisplay): log.debug('Recent file name: %s', filename) - action = QtGui.QAction(u'&%d %s' % (fileId + 1, - QtCore.QFileInfo(filename).fileName()), self) + action = base_action(self, u'') + action.setText(u'&%d %s' % + (fileId + 1, QtCore.QFileInfo(filename).fileName())) action.setData(QtCore.QVariant(filename)) self.connect(action, QtCore.SIGNAL(u'triggered()'), self.ServiceManagerContents.onRecentServiceClicked) diff --git a/openlp/core/ui/printservicedialog.py b/openlp/core/ui/printservicedialog.py index 97f4b4060..9593e9ec4 100644 --- a/openlp/core/ui/printservicedialog.py +++ b/openlp/core/ui/printservicedialog.py @@ -132,6 +132,8 @@ class Ui_PrintServiceDialog(object): self.groupLayout = QtGui.QVBoxLayout() self.slideTextCheckBox = QtGui.QCheckBox() self.groupLayout.addWidget(self.slideTextCheckBox) + self.pageBreakAfterText = QtGui.QCheckBox() + self.groupLayout.addWidget(self.pageBreakAfterText) self.notesCheckBox = QtGui.QCheckBox() self.groupLayout.addWidget(self.notesCheckBox) self.metaDataCheckBox = QtGui.QCheckBox() @@ -149,6 +151,8 @@ class Ui_PrintServiceDialog(object): printServiceDialog.setWindowTitle(UiStrings.PrintServiceOrder) self.slideTextCheckBox.setText(translate('OpenLP.PrintServiceForm', 'Include slide text if available')) + self.pageBreakAfterText.setText(translate('OpenLP.PrintServiceForm', + 'Add page break before each text item.')) self.notesCheckBox.setText(translate('OpenLP.PrintServiceForm', 'Include service item notes')) self.metaDataCheckBox.setText(translate('OpenLP.PrintServiceForm', diff --git a/openlp/core/ui/printserviceform.py b/openlp/core/ui/printserviceform.py index 4e0f018a4..01b937d61 100644 --- a/openlp/core/ui/printserviceform.py +++ b/openlp/core/ui/printserviceform.py @@ -24,12 +24,65 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### import datetime +import os from PyQt4 import QtCore, QtGui +from lxml import html -from openlp.core.lib import translate +from openlp.core.lib import translate, get_text_file_string from openlp.core.lib.ui import UiStrings from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize +from openlp.core.utils import AppLocation + +DEFAULT_CSS = """/* +Edit this file to customize the service order print. Note, that not all CSS +properties are supported. See: +http://doc.trolltech.com/4.7/richtext-html-subset.html#css-properties +*/ + +.serviceTitle { + font-weight:600; + font-size:x-large; + color:black; +} + +.itemTitle { + font-weight:600; + font-size:large; + color:black; +} + +.itemText { + color:black; +} + +.itemFooter { + font-size:8px; + color:black; +} + +.itemNotesTitle { + font-weight:bold; + font-size:12px; + color:black; +} + +.itemNotesText { + font-size:11px; + color:black; +} + +.customNotesTitle { + font-weight:bold; + font-size:11px; + color:black; +} + +.customNotesText { + font-size:11px; + color:black; +} +""" class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): @@ -50,6 +103,10 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): settings.beginGroup(u'advanced') self.slideTextCheckBox.setChecked(settings.value( u'print slide text', QtCore.QVariant(False)).toBool()) + self.pageBreakAfterText.setChecked(settings.value( + u'add page break', QtCore.QVariant(False)).toBool()) + if not self.slideTextCheckBox.isChecked(): + self.pageBreakAfterText.setDisabled(True) self.metaDataCheckBox.setChecked(settings.value( u'print file meta data', QtCore.QVariant(False)).toBool()) self.notesCheckBox.setChecked(settings.value( @@ -76,6 +133,9 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): QtCore.SIGNAL(u'triggered()'), self.copyText) QtCore.QObject.connect(self.htmlCopy, QtCore.SIGNAL(u'triggered()'), self.copyHtmlText) + QtCore.QObject.connect(self.slideTextCheckBox, + QtCore.SIGNAL(u'stateChanged(int)'), + self.onSlideTextCheckBoxChanged) self.updatePreviewText() def toggleOptions(self, checked): @@ -93,59 +153,124 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): """ Creates the html text and updates the html of *self.document*. """ - text = u'' - if self.titleLineEdit.text(): - text += u'

%s

' % unicode(self.titleLineEdit.text()) - for item in self.serviceManager.serviceItems: + html_data = html.fromstring( + u'%s' % unicode(self.titleLineEdit.text())) + css_path = os.path.join( + AppLocation.get_data_path(), u'servicePrint.css') + if not os.path.isfile(css_path): + # Create default css file. + css_file = open(css_path, u'w') + css_file.write(DEFAULT_CSS) + css_file.close() + custom_css = get_text_file_string(css_path) + self._addChildToParent( + u'style', custom_css, html_data.head, u'type', u'text/css') + self._addChildToParent(u'body', parent=html_data) + self._addChildToParent(u'span', unicode(self.titleLineEdit.text()), + html_data.body, u'class', u'serviceTitle') + for index, item in enumerate(self.serviceManager.serviceItems): item = item[u'service_item'] + div = self._addChildToParent(u'div', parent=html_data.body) # Add the title of the service item. - text += u'

%s

' % (item.icon, - item.get_display_title()) - # Add slide text of the service item. + item_title = self._addChildToParent( + u'h2', parent=div, attribute=u'class', value=u'itemTitle') + self._addChildToParent( + u'img', parent=item_title, attribute=u'src', value=item.icon) + self._fromstring( + u' %s' % item.get_display_title(), item_title) if self.slideTextCheckBox.isChecked(): + # Add the text of the service item. if item.is_text(): - # Add the text of the service item. - verse = None + verse_def = None for slide in item.get_frames(): - if not verse: - text += u'

' + slide[u'html'] - verse = slide[u'verseTag'] - elif verse != slide[u'verseTag']: - text += u'<\p>

' + slide[u'html'] - verse = slide[u'verseTag'] + if not verse_def or verse_def != slide[u'verseTag']: + p = self._addChildToParent(u'p', parent=div, + attribute=u'class', value=u'itemText') else: - text += u'
' + slide[u'html'] - text += u'

' + self._addChildToParent(u'br', parent=p) + self._fromstring(u'%s' % slide[u'html'], p) + verse_def = slide[u'verseTag'] + # Break the page before the div element. + if index != 0 and self.pageBreakAfterText.isChecked(): + div.set(u'style', u'page-break-before:always') + # Add the image names of the service item. elif item.is_image(): - # Add the image names of the service item. - text += u'
    ' + ol = self._addChildToParent(u'ol', parent=div) for slide in range(len(item.get_frames())): - text += u'
  1. %s

  2. ' % \ - item.get_frame_title(slide) - text += u'
' + self._addChildToParent(u'li', item.get_frame_title(slide), ol) + # add footer if item.foot_text: - # add footer - text += u'

%s

' % item.foot_text + self._fromstring( + item.foot_text, div, u'class', u'itemFooter') # Add service items' notes. if self.notesCheckBox.isChecked(): if item.notes: - text += u'

%s

%s' % (translate( - 'OpenLP.ServiceManager', 'Notes:'), - item.notes.replace(u'\n', u'
')) + p = self._addChildToParent(u'p', parent=div) + self._addChildToParent(u'span', unicode( + translate('OpenLP.ServiceManager', 'Notes:')), p, + u'class', u'itemNotesTitle') + self._fromstring(u' %s' % item.notes.replace( + u'\n', u'
'), p, u'class', u'itemNotesText') # Add play length of media files. if item.is_media() and self.metaDataCheckBox.isChecked(): tme = item.media_length if item.end_time > 0: tme = item.end_time - item.start_time - text += u'

%s %s

' % (translate( - 'OpenLP.ServiceManager', u'Playing time:'), - unicode(datetime.timedelta(seconds=tme))) + title = self._fromstring(u'

%s

' % + translate('OpenLP.ServiceManager', 'Playing time:'), div) + self._fromstring(u'%s' % + unicode(datetime.timedelta(seconds=tme)), title) + # Add the custom service notes: if self.footerTextEdit.toPlainText(): - text += u'

%s

%s' % (translate('OpenLP.ServiceManager', - u'Custom Service Notes:'), self.footerTextEdit.toPlainText()) - self.document.setHtml(text) + self._addChildToParent(u'span', translate('OpenLP.ServiceManager', + u'Custom Service Notes:'), div, u'class', u'customNotesTitle') + self._addChildToParent( + u'span', u' %s' % self.footerTextEdit.toPlainText(), div, + u'class', u'customNotesText') + self.document.setHtml(html.tostring(html_data)) self.previewWidget.updatePreview() + def _addChildToParent(self, tag, text=None, parent=None, attribute=None, + value=None): + """ + Creates a html element. If ``text`` is given, the element's text will + set and if a ``parent`` is given, the element is appended. + + ``tag`` + The html tag, e. g. ``u'span'``. Defaults to ``None``. + + ``text`` + The text for the tag. Defaults to ``None``. + + ``parent`` + The parent element. Defaults to ``None``. + + ``attribute`` + An optional attribute, for instance ``u'class``. + + ``value`` + The value for the given ``attribute``. It does not have a meaning, + if the attribute is left to its default. + """ + element = html.Element(tag) + if text is not None: + element.text = unicode(text) + if parent is not None: + parent.append(element) + if attribute is not None: + element.set(attribute, value if value is not None else u'') + return element + + def _fromstring(self, string, parent, attribute=None, value=None): + """ + This is used to create a child html element from a string. + """ + element = html.fromstring(string) + if attribute is not None: + element.set(attribute, value if value is not None else u'') + parent.append(element) + return element + def paintRequested(self, printer): """ Paint the preview of the *self.document*. @@ -232,6 +357,13 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): else: self.copyTextButton.setText(UiStrings.CopyToText) + def onSlideTextCheckBoxChanged(self, state): + """ + Disable or enable the ``pageBreakAfterText`` checkbox as it should only + be enabled, when the ``slideTextCheckBox`` is enabled. + """ + self.pageBreakAfterText.setDisabled(state == QtCore.Qt.Unchecked) + def saveOptions(self): """ Save the settings and close the dialog. @@ -241,6 +373,8 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): settings.beginGroup(u'advanced') settings.setValue(u'print slide text', QtCore.QVariant(self.slideTextCheckBox.isChecked())) + settings.setValue(u'add page break', + QtCore.QVariant(self.pageBreakAfterText.isChecked())) settings.setValue(u'print file meta data', QtCore.QVariant(self.metaDataCheckBox.isChecked())) settings.setValue(u'print notes', diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 9c1c63917..ba9ca718a 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -32,14 +32,16 @@ log = logging.getLogger(__name__) from PyQt4 import QtCore, QtGui -from openlp.core.lib import OpenLPToolbar, ServiceItem, context_menu_action, \ - Receiver, build_icon, ItemCapabilities, SettingsManager, translate +from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \ + ItemCapabilities, SettingsManager, translate from openlp.core.lib.theme import ThemeLevel -from openlp.core.lib.ui import UiStrings, critical_error_message_box +from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ + context_menu_action, find_and_set_in_combo_box from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm from openlp.core.ui.printserviceform import PrintServiceForm from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \ split_filename +from openlp.core.utils.actions import ActionList, CategoryOrder class ServiceManagerList(QtGui.QTreeWidget): """ @@ -164,38 +166,55 @@ class ServiceManager(QtGui.QWidget): u':/services/service_top.png', translate('OpenLP.ServiceManager', 'Move item to the top of the service.'), - self.onServiceTop, shortcut=QtCore.Qt.Key_Home) + self.onServiceTop, shortcuts=[QtCore.Qt.Key_Home]) + self.serviceManagerList.moveTop.setObjectName(u'moveTop') + action_list = ActionList.get_instance() + action_list.add_category(UiStrings.Service, CategoryOrder.standardToolbar) + action_list.add_action( + self.serviceManagerList.moveTop, UiStrings.Service) self.serviceManagerList.moveUp = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Move &up'), u':/services/service_up.png', translate('OpenLP.ServiceManager', 'Move item up one position in the service.'), - self.onServiceUp, shortcut=QtCore.Qt.Key_PageUp) + self.onServiceUp, shortcuts=[QtCore.Qt.Key_PageUp]) + self.serviceManagerList.moveUp.setObjectName(u'moveUp') + action_list.add_action(self.serviceManagerList.moveUp, UiStrings.Service) self.serviceManagerList.moveDown = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Move &down'), u':/services/service_down.png', translate('OpenLP.ServiceManager', 'Move item down one position in the service.'), - self.onServiceDown, shortcut=QtCore.Qt.Key_PageDown) + self.onServiceDown, shortcuts=[QtCore.Qt.Key_PageDown]) + self.serviceManagerList.moveDown.setObjectName(u'moveDown') + action_list.add_action( + self.serviceManagerList.moveDown, UiStrings.Service) self.serviceManagerList.moveBottom = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Move to &bottom'), u':/services/service_bottom.png', translate('OpenLP.ServiceManager', 'Move item to the end of the service.'), - self.onServiceEnd, shortcut=QtCore.Qt.Key_End) + self.onServiceEnd, shortcuts=[QtCore.Qt.Key_End]) + self.serviceManagerList.moveBottom.setObjectName(u'moveBottom') + action_list.add_action( + self.serviceManagerList.moveBottom, UiStrings.Service) self.serviceManagerList.down = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Move &down'), None, translate('OpenLP.ServiceManager', 'Moves the selection down the window.'), - self.onMoveSelectionDown, shortcut=QtCore.Qt.Key_Down) + self.onMoveSelectionDown, shortcuts=[QtCore.Qt.Key_Down]) + self.serviceManagerList.down.setObjectName(u'down') + action_list.add_action(self.serviceManagerList.down) self.serviceManagerList.down.setVisible(False) self.serviceManagerList.up = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Move up'), None, translate('OpenLP.ServiceManager', 'Moves the selection up the window.'), - self.onMoveSelectionUp, shortcut=QtCore.Qt.Key_Up) + self.onMoveSelectionUp, shortcuts=[QtCore.Qt.Key_Up]) + self.serviceManagerList.up.setObjectName(u'up') + action_list.add_action(self.serviceManagerList.up) self.serviceManagerList.up.setVisible(False) self.orderToolbar.addSeparator() self.serviceManagerList.delete = self.orderToolbar.addToolbarButton( @@ -210,22 +229,28 @@ class ServiceManager(QtGui.QWidget): u':/services/service_expand_all.png', translate('OpenLP.ServiceManager', 'Expand all the service items.'), - self.onExpandAll, shortcut=QtCore.Qt.Key_Plus) + self.onExpandAll, shortcuts=[QtCore.Qt.Key_Plus]) + self.serviceManagerList.expand.setObjectName(u'expand') + action_list.add_action(self.serviceManagerList.expand, UiStrings.Service) self.serviceManagerList.collapse = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', '&Collapse all'), u':/services/service_collapse_all.png', translate('OpenLP.ServiceManager', 'Collapse all the service items.'), - self.onCollapseAll, shortcut=QtCore.Qt.Key_Minus) + self.onCollapseAll, shortcuts=[QtCore.Qt.Key_Minus]) + self.serviceManagerList.collapse.setObjectName(u'collapse') + action_list.add_action( + self.serviceManagerList.collapse, UiStrings.Service) self.orderToolbar.addSeparator() self.serviceManagerList.makeLive = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Go Live'), u':/general/general_live.png', translate('OpenLP.ServiceManager', - 'Send the selected item to Live.'), - self.makeLive, shortcut=QtCore.Qt.Key_Enter, - alternate=QtCore.Qt.Key_Return) - self.orderToolbar.setObjectName(u'orderToolbar') + 'Send the selected item to Live.'), self.makeLive, + shortcuts=[QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return]) + self.serviceManagerList.makeLive.setObjectName(u'orderToolbar') + action_list.add_action( + self.serviceManagerList.makeLive, UiStrings.Service) self.layout.addWidget(self.orderToolbar) # Connect up our signals and slots QtCore.QObject.connect(self.themeComboBox, @@ -300,7 +325,6 @@ class ServiceManager(QtGui.QWidget): self.themeMenu = QtGui.QMenu( translate('OpenLP.ServiceManager', '&Change Item Theme')) self.menu.addMenu(self.themeMenu) - self.setServiceHotkeys() self.serviceManagerList.addActions( [self.serviceManagerList.moveDown, self.serviceManagerList.moveUp, @@ -314,19 +338,6 @@ class ServiceManager(QtGui.QWidget): ]) self.configUpdated() - def setServiceHotkeys(self): - actionList = self.mainwindow.actionList - actionList.add_action(self.serviceManagerList.moveDown, u'Service') - actionList.add_action(self.serviceManagerList.moveUp, u'Service') - actionList.add_action(self.serviceManagerList.moveTop, u'Service') - actionList.add_action(self.serviceManagerList.moveBottom, u'Service') - actionList.add_action(self.serviceManagerList.makeLive, u'Service') - actionList.add_action(self.serviceManagerList.up, u'Service') - actionList.add_action(self.serviceManagerList.down, u'Service') - actionList.add_action(self.serviceManagerList.expand, u'Service') - actionList.add_action(self.serviceManagerList.collapse, u'Service') - - def setModified(self, modified=True): """ Setter for property "modified". Sets whether or not the current service @@ -691,9 +702,9 @@ class ServiceManager(QtGui.QWidget): Called by the SlideController to request a preview item be made live and allows the next preview to be updated if relevent. """ - id, row = message.split(u':') + uuid, row = message.split(u':') for sitem in self.serviceItems: - if sitem[u'service_item']._uuid == id: + if sitem[u'service_item']._uuid == uuid: item = self.serviceManagerList.topLevelItem(sitem[u'order'] - 1) self.serviceManagerList.setCurrentItem(item) self.makeLive(int(row)) @@ -1021,7 +1032,7 @@ class ServiceManager(QtGui.QWidget): editId, uuid = message.split(u':') for item in self.serviceItems: if item[u'service_item']._uuid == uuid: - item[u'service_item'].edit_id = editId + item[u'service_item'].edit_id = int(editId) self.setModified(True) def replaceServiceItem(self, newItem): @@ -1259,15 +1270,9 @@ class ServiceManager(QtGui.QWidget): for theme in theme_list: self.themeComboBox.addItem(theme) action = context_menu_action(self.serviceManagerList, None, theme, - self.onThemeChangeAction) + self.onThemeChangeAction, context=QtCore.Qt.WidgetShortcut) self.themeMenu.addAction(action) - index = self.themeComboBox.findText(self.service_theme, - QtCore.Qt.MatchExactly) - # Not Found - if index == -1: - index = 0 - self.service_theme = u'' - self.themeComboBox.setCurrentIndex(index) + find_and_set_in_combo_box(self.themeComboBox, self.service_theme) self.mainwindow.renderManager.set_service_theme(self.service_theme) self.regenerateServiceItems() diff --git a/openlp/core/ui/shortcutlistdialog.py b/openlp/core/ui/shortcutlistdialog.py index 4e5b9e270..288086cba 100644 --- a/openlp/core/ui/shortcutlistdialog.py +++ b/openlp/core/ui/shortcutlistdialog.py @@ -31,41 +31,72 @@ from openlp.core.lib import translate, build_icon class Ui_ShortcutListDialog(object): def setupUi(self, shortcutListDialog): shortcutListDialog.setObjectName(u'shortcutListDialog') - self.dialogLayout = QtGui.QVBoxLayout(shortcutListDialog) - self.dialogLayout.setObjectName(u'dialogLayout') + shortcutListDialog.resize(500, 438) + self.shortcutListLayout = QtGui.QVBoxLayout(shortcutListDialog) + self.shortcutListLayout.setObjectName(u'shortcutListLayout') + self.descriptionLabel = QtGui.QLabel(shortcutListDialog) + self.descriptionLabel.setObjectName(u'descriptionLabel') + self.descriptionLabel.setWordWrap(True) + self.shortcutListLayout.addWidget(self.descriptionLabel) self.treeWidget = QtGui.QTreeWidget(shortcutListDialog) - self.treeWidget.setAlternatingRowColors(True) self.treeWidget.setObjectName(u'treeWidget') + self.treeWidget.setAlternatingRowColors(True) self.treeWidget.setColumnCount(3) - self.dialogLayout.addWidget(self.treeWidget) - self.defaultButton = QtGui.QRadioButton(shortcutListDialog) - self.defaultButton.setChecked(True) - self.defaultButton.setObjectName(u'defaultButton') - self.dialogLayout.addWidget(self.defaultButton) - self.customLayout = QtGui.QHBoxLayout() - self.customLayout.setObjectName(u'customLayout') - self.customButton = QtGui.QRadioButton(shortcutListDialog) - self.customButton.setObjectName(u'customButton') - self.customLayout.addWidget(self.customButton) - self.shortcutButton = QtGui.QPushButton(shortcutListDialog) - self.shortcutButton.setIcon( + self.treeWidget.setColumnWidth(0, 250) + self.shortcutListLayout.addWidget(self.treeWidget) + self.detailsLayout = QtGui.QGridLayout() + self.detailsLayout.setObjectName(u'detailsLayout') + self.detailsLayout.setContentsMargins(-1, 0, -1, -1) + self.defaultRadioButton = QtGui.QRadioButton(shortcutListDialog) + self.defaultRadioButton.setObjectName(u'defaultRadioButton') + self.defaultRadioButton.setChecked(True) + self.detailsLayout.addWidget(self.defaultRadioButton, 0, 0, 1, 1) + self.customRadioButton = QtGui.QRadioButton(shortcutListDialog) + self.customRadioButton.setObjectName(u'customRadioButton') + self.detailsLayout.addWidget(self.customRadioButton, 1, 0, 1, 1) + self.primaryLayout = QtGui.QHBoxLayout() + self.primaryLayout.setObjectName(u'primaryLayout') + self.primaryPushButton = QtGui.QPushButton(shortcutListDialog) + self.primaryPushButton.setObjectName(u'primaryPushButton') + self.primaryPushButton.setMinimumSize(QtCore.QSize(84, 0)) + self.primaryPushButton.setIcon( build_icon(u':/system/system_configure_shortcuts.png')) - self.shortcutButton.setCheckable(True) - self.shortcutButton.setObjectName(u'shortcutButton') - self.customLayout.addWidget(self.shortcutButton) - self.clearShortcutButton = QtGui.QToolButton(shortcutListDialog) - self.clearShortcutButton.setIcon( + self.primaryPushButton.setCheckable(True) + self.primaryLayout.addWidget(self.primaryPushButton) + self.clearPrimaryButton = QtGui.QToolButton(shortcutListDialog) + self.clearPrimaryButton.setObjectName(u'clearPrimaryButton') + self.clearPrimaryButton.setMinimumSize(QtCore.QSize(0, 16)) + self.clearPrimaryButton.setIcon( build_icon(u':/system/clear_shortcut.png')) - self.clearShortcutButton.setAutoRaise(True) - self.clearShortcutButton.setObjectName(u'clearShortcutButton') - self.customLayout.addWidget(self.clearShortcutButton) - self.customLayout.addStretch() - self.dialogLayout.addLayout(self.customLayout) + self.primaryLayout.addWidget(self.clearPrimaryButton) + self.detailsLayout.addLayout(self.primaryLayout, 1, 1, 1, 1) + self.alternateLayout = QtGui.QHBoxLayout() + self.alternateLayout.setObjectName(u'alternateLayout') + self.alternatePushButton = QtGui.QPushButton(shortcutListDialog) + self.alternatePushButton.setObjectName(u'alternatePushButton') + self.alternatePushButton.setCheckable(True) + self.alternatePushButton.setIcon( + build_icon(u':/system/system_configure_shortcuts.png')) + self.alternateLayout.addWidget(self.alternatePushButton) + self.clearAlternateButton = QtGui.QToolButton(shortcutListDialog) + self.clearAlternateButton.setObjectName(u'clearAlternateButton') + self.clearAlternateButton.setIcon( + build_icon(u':/system/clear_shortcut.png')) + self.alternateLayout.addWidget(self.clearAlternateButton) + self.detailsLayout.addLayout(self.alternateLayout, 1, 2, 1, 1) + self.primaryLabel = QtGui.QLabel(shortcutListDialog) + self.primaryLabel.setObjectName(u'primaryLabel') + self.detailsLayout.addWidget(self.primaryLabel, 0, 1, 1, 1) + self.alternateLabel = QtGui.QLabel(shortcutListDialog) + self.alternateLabel.setObjectName(u'alternateLabel') + self.detailsLayout.addWidget(self.alternateLabel, 0, 2, 1, 1) + self.shortcutListLayout.addLayout(self.detailsLayout) self.buttonBox = QtGui.QDialogButtonBox(shortcutListDialog) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | - QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Reset) self.buttonBox.setObjectName(u'buttonBox') - self.dialogLayout.addWidget(self.buttonBox) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | + QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.RestoreDefaults) + self.shortcutListLayout.addWidget(self.buttonBox) self.retranslateUi(shortcutListDialog) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'), shortcutListDialog.accept) @@ -76,13 +107,24 @@ class Ui_ShortcutListDialog(object): def retranslateUi(self, shortcutListDialog): shortcutListDialog.setWindowTitle( translate('OpenLP.ShortcutListDialog', 'Customize Shortcuts')) + self.descriptionLabel.setText(translate('OpenLP.ShortcutListDialog', + 'Select an action and click one of the buttons below to start ' + 'capturing a new primary or alternate shortcut, respectively.')) self.treeWidget.setHeaderLabels([ translate('OpenLP.ShortcutListDialog', 'Action'), translate('OpenLP.ShortcutListDialog', 'Shortcut'), translate('OpenLP.ShortcutListDialog', 'Alternate')]) - self.defaultButton.setText( - translate('OpenLP.ShortcutListDialog', 'Default: %s')) - self.customButton.setText( - translate('OpenLP.ShortcutListDialog', 'Custom:')) - self.shortcutButton.setText( - translate('OpenLP.ShortcutListDialog', 'None')) + self.defaultRadioButton.setText( + translate('OpenLP.ShortcutListDialog', 'Default')) + self.customRadioButton.setText( + translate('OpenLP.ShortcutListDialog', 'Custom')) + self.primaryPushButton.setToolTip( + translate('OpenLP.ShortcutListDialog', 'Capture shortcut.')) + self.alternatePushButton.setToolTip( + translate('OpenLP.ShortcutListDialog', 'Capture shortcut.')) + self.clearPrimaryButton.setToolTip( + translate('OpenLP.ShortcutListDialog', + 'Restore the default shortcut of this action.')) + self.clearAlternateButton.setToolTip( + translate('OpenLP.ShortcutListDialog', + 'Restore the default shortcut of this action.')) diff --git a/openlp/core/ui/shortcutlistform.py b/openlp/core/ui/shortcutlistform.py index e87ba3ada..26bfddadd 100644 --- a/openlp/core/ui/shortcutlistform.py +++ b/openlp/core/ui/shortcutlistform.py @@ -30,6 +30,7 @@ import re from PyQt4 import QtCore, QtGui from openlp.core.utils import translate +from openlp.core.utils.actions import ActionList from shortcutlistdialog import Ui_ShortcutListDialog REMOVE_AMPERSAND = re.compile(r'&{1}') @@ -41,72 +42,391 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog): The shortcut list dialog """ - def __init__(self, parent): - """ - Do some initialisation stuff - """ + def __init__(self, parent=None): QtGui.QDialog.__init__(self, parent) self.setupUi(self) - self.actionList = None - self.captureShortcut = False - QtCore.QObject.connect(self.shortcutButton, - QtCore.SIGNAL(u'toggled(bool)'), self.onShortcutButtonClicked) + self.changedActions = {} + self.action_list = ActionList.get_instance() + QtCore.QObject.connect(self.primaryPushButton, + QtCore.SIGNAL(u'toggled(bool)'), self.onPrimaryPushButtonClicked) + QtCore.QObject.connect(self.alternatePushButton, + QtCore.SIGNAL(u'toggled(bool)'), self.onAlternatePushButtonClicked) + QtCore.QObject.connect(self.treeWidget, QtCore.SIGNAL( + u'currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)'), + self.onCurrentItemChanged) + QtCore.QObject.connect(self.treeWidget, + QtCore.SIGNAL(u'itemDoubleClicked(QTreeWidgetItem*, int)'), + self.onItemDoubleClicked) + QtCore.QObject.connect(self.clearPrimaryButton, + QtCore.SIGNAL(u'clicked(bool)'), self.onClearPrimaryButtonClicked) + QtCore.QObject.connect(self.clearAlternateButton, + QtCore.SIGNAL(u'clicked(bool)'), self.onClearAlternateButtonClicked) + QtCore.QObject.connect(self.buttonBox, + QtCore.SIGNAL(u'clicked(QAbstractButton*)'), + self.onRestoreDefaultsClicked) + QtCore.QObject.connect(self.defaultRadioButton, + QtCore.SIGNAL(u'clicked(bool)'), self.onDefaultRadioButtonClicked) + QtCore.QObject.connect(self.customRadioButton, + QtCore.SIGNAL(u'clicked(bool)'), self.onCustomRadioButtonClicked) + + def keyPressEvent(self, event): + if self.primaryPushButton.isChecked() or \ + self.alternatePushButton.isChecked(): + event.ignore() + elif event.key() == QtCore.Qt.Key_Escape: + event.accept() + self.close() def keyReleaseEvent(self, event): - Qt = QtCore.Qt - if not self.captureShortcut: + if not self.primaryPushButton.isChecked() and \ + not self.alternatePushButton.isChecked(): return key = event.key() - if key == Qt.Key_Shift or key == Qt.Key_Control or \ - key == Qt.Key_Meta or key == Qt.Key_Alt: + if key == QtCore.Qt.Key_Shift or key == QtCore.Qt.Key_Control or \ + key == QtCore.Qt.Key_Meta or key == QtCore.Qt.Key_Alt: return key_string = QtGui.QKeySequence(key).toString() - if event.modifiers() & Qt.ControlModifier == Qt.ControlModifier: + if event.modifiers() & QtCore.Qt.ControlModifier == \ + QtCore.Qt.ControlModifier: key_string = u'Ctrl+' + key_string - if event.modifiers() & Qt.AltModifier == Qt.AltModifier: + if event.modifiers() & QtCore.Qt.AltModifier == QtCore.Qt.AltModifier: key_string = u'Alt+' + key_string - if event.modifiers() & Qt.ShiftModifier == Qt.ShiftModifier: + if event.modifiers() & QtCore.Qt.ShiftModifier == \ + QtCore.Qt.ShiftModifier: key_string = u'Shift+' + key_string key_sequence = QtGui.QKeySequence(key_string) - existing_key = QtGui.QKeySequence(u'Ctrl+Shift+F8') - if key_sequence == existing_key: - QtGui.QMessageBox.warning( - self, + # The action we are attempting to change. + changing_action = self._currentItemAction() + shortcut_valid = True + for category in self.action_list.categories: + for action in category.actions: + shortcuts = self._actionShortcuts(action) + if key_sequence not in shortcuts: + continue + if action is changing_action: + if self.primaryPushButton.isChecked() and \ + shortcuts.index(key_sequence) == 0: + continue + if self.alternatePushButton.isChecked() and \ + shortcuts.index(key_sequence) == 1: + continue + # Have the same parent, thus they cannot have the same shortcut. + if action.parent() is changing_action.parent(): + shortcut_valid = False + # The new shortcut is already assigned, but if both shortcuts + # are only valid in a different widget the new shortcut is + # vaild, because they will not interfere. + if action.shortcutContext() in [QtCore.Qt.WindowShortcut, + QtCore.Qt.ApplicationShortcut]: + shortcut_valid = False + if changing_action.shortcutContext() in \ + [QtCore.Qt.WindowShortcut, QtCore.Qt.ApplicationShortcut]: + shortcut_valid = False + if not shortcut_valid: + QtGui.QMessageBox.warning(self, translate('OpenLP.ShortcutListDialog', 'Duplicate Shortcut'), unicode(translate('OpenLP.ShortcutListDialog', 'The shortcut ' - '"%s" is already assigned to another action, please ' - 'use a different shortcut.')) % key_sequence.toString(), + '"%s" is already assigned to another action, please ' + 'use a different shortcut.')) % key_sequence.toString(), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok ) else: - self.shortcutButton.setText(key_sequence.toString()) - self.shortcutButton.setChecked(False) - self.captureShortcut = False + if self.primaryPushButton.isChecked(): + self._adjustButton(self.primaryPushButton, + False, text=key_sequence.toString()) + elif self.alternatePushButton.isChecked(): + self._adjustButton(self.alternatePushButton, + False, text=key_sequence.toString()) - def exec_(self, actionList): - self.actionList = actionList - self.refreshActions() + def exec_(self): + self.changedActions = {} + self.reloadShortcutList() + self._adjustButton(self.primaryPushButton, False, False, u'') + self._adjustButton(self.alternatePushButton, False, False, u'') return QtGui.QDialog.exec_(self) - def refreshActions(self): + def reloadShortcutList(self): + """ + Reload the ``treeWidget`` list to add new and remove old actions. + """ self.treeWidget.clear() - for category in self.actionList.categories: + for category in self.action_list.categories: + # Check if the category is for internal use only. + if category.name is None: + continue item = QtGui.QTreeWidgetItem([category.name]) for action in category.actions: actionText = REMOVE_AMPERSAND.sub('', unicode(action.text())) - if (len(action.shortcuts()) == 2): - shortcutText = action.shortcuts()[0].toString() - alternateText = action.shortcuts()[1].toString() - else: - shortcutText = action.shortcut().toString() - alternateText = u'' - actionItem = QtGui.QTreeWidgetItem( - [actionText, shortcutText, alternateText]) + actionItem = QtGui.QTreeWidgetItem([actionText]) actionItem.setIcon(0, action.icon()) + actionItem.setData(0, + QtCore.Qt.UserRole, QtCore.QVariant(action)) item.addChild(actionItem) - item.setExpanded(True) self.treeWidget.addTopLevelItem(item) + item.setExpanded(True) + self.refreshShortcutList() - def onShortcutButtonClicked(self, toggled): - self.captureShortcut = toggled + def refreshShortcutList(self): + """ + This refreshes the item's shortcuts shown in the list. Note, this + neither adds new actions nor removes old actions. + """ + iterator = QtGui.QTreeWidgetItemIterator(self.treeWidget) + while iterator.value(): + item = iterator.value() + iterator += 1 + action = self._currentItemAction(item) + if action is None: + continue + shortcuts = self._actionShortcuts(action) + if len(shortcuts) == 0: + item.setText(1, u'') + item.setText(2, u'') + elif len(shortcuts) == 1: + item.setText(1, shortcuts[0].toString()) + item.setText(2, u'') + else: + item.setText(1, shortcuts[0].toString()) + item.setText(2, shortcuts[1].toString()) + self.onCurrentItemChanged() + + def onPrimaryPushButtonClicked(self, toggled): + """ + Save the new primary shortcut. + """ + self.customRadioButton.setChecked(True) + if toggled: + self.alternatePushButton.setChecked(False) + return + action = self._currentItemAction() + if action is None: + return + shortcuts = self._actionShortcuts(action) + new_shortcuts = [QtGui.QKeySequence(self.primaryPushButton.text())] + if len(shortcuts) == 2: + new_shortcuts.append(shortcuts[1]) + self.changedActions[action] = new_shortcuts + self.refreshShortcutList() + + def onAlternatePushButtonClicked(self, toggled): + """ + Save the new alternate shortcut. + """ + self.customRadioButton.setChecked(True) + if toggled: + self.primaryPushButton.setChecked(False) + return + action = self._currentItemAction() + if action is None: + return + shortcuts = self._actionShortcuts(action) + new_shortcuts = [] + if len(shortcuts) != 0: + new_shortcuts.append(shortcuts[0]) + new_shortcuts.append( + QtGui.QKeySequence(self.alternatePushButton.text())) + self.changedActions[action] = new_shortcuts + self.refreshShortcutList() + + def onItemDoubleClicked(self, item, column): + """ + A item has been double clicked. The ``primaryPushButton`` will be + checked and the item's shortcut will be displayed. + """ + action = self._currentItemAction(item) + if action is None: + return + self.primaryPushButton.setChecked(column in [0, 1]) + self.alternatePushButton.setChecked(column not in [0, 1]) + if column in [0, 1]: + self.primaryPushButton.setFocus(QtCore.Qt.OtherFocusReason) + else: + self.alternatePushButton.setFocus(QtCore.Qt.OtherFocusReason) + self.onCurrentItemChanged(item) + + def onCurrentItemChanged(self, item=None, previousItem=None): + """ + A item has been pressed. We adjust the button's text to the action's + shortcut which is encapsulate in the item. + """ + action = self._currentItemAction(item) + self.primaryPushButton.setEnabled(action is not None) + self.alternatePushButton.setEnabled(action is not None) + primary_text = u'' + alternate_text = u'' + primary_label_text = u'' + alternate_label_text = u'' + if action is None: + self.primaryPushButton.setChecked(False) + self.alternatePushButton.setChecked(False) + else: + if len(action.defaultShortcuts) != 0: + primary_label_text = action.defaultShortcuts[0].toString() + if len(action.defaultShortcuts) == 2: + alternate_label_text = action.defaultShortcuts[1].toString() + shortcuts = self._actionShortcuts(action) + # We do not want to loose pending changes, that is why we have to + # keep the text when, this function has not been triggered by a signal. + if item is None: + primary_text = self.primaryPushButton.text() + alternate_text = self.alternatePushButton.text() + elif len(shortcuts) == 1: + primary_text = shortcuts[0].toString() + elif len(shortcuts) == 2: + primary_text = shortcuts[0].toString() + alternate_text = shortcuts[1].toString() + self.primaryPushButton.setText(primary_text) + self.alternatePushButton.setText(alternate_text) + self.primaryLabel.setText(primary_label_text) + self.alternateLabel.setText(alternate_label_text) + # We do not want to toggle and radio button, as the function has not + # been triggered by a signal. + if item is None: + return + if primary_label_text == primary_text and \ + alternate_label_text == alternate_text: + self.defaultRadioButton.toggle() + else: + self.customRadioButton.toggle() + + def onRestoreDefaultsClicked(self, button): + """ + Restores all default shortcuts. + """ + if self.buttonBox.buttonRole(button) != QtGui.QDialogButtonBox.ResetRole: + return + if QtGui.QMessageBox.question(self, + translate('OpenLP.ShortcutListDialog', 'Restore Default Shortcuts'), + translate('OpenLP.ShortcutListDialog', 'Do you want to restore all ' + 'shortcuts to their defaults?'), QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Yes | + QtGui.QMessageBox.No)) == QtGui.QMessageBox.No: + return + self._adjustButton(self.primaryPushButton, False, text=u'') + self._adjustButton(self.alternatePushButton, False, text=u'') + for category in self.action_list.categories: + for action in category.actions: + self.changedActions[action] = action.defaultShortcuts + self.refreshShortcutList() + + def onDefaultRadioButtonClicked(self, toggled): + """ + The default radio button has been clicked, which means we have to make + sure, that we use the default shortcuts for the action. + """ + if not toggled: + return + action = self._currentItemAction() + if action is None: + return + temp_shortcuts = self._actionShortcuts(action) + self.changedActions[action] = action.defaultShortcuts + self.refreshShortcutList() + primary_button_text = u'' + alternate_button_text = u'' + if len(temp_shortcuts) != 0: + primary_button_text = temp_shortcuts[0].toString() + if len(temp_shortcuts) == 2: + alternate_button_text = temp_shortcuts[1].toString() + self.primaryPushButton.setText(primary_button_text) + self.alternatePushButton.setText(alternate_button_text) + + def onCustomRadioButtonClicked(self, toggled): + """ + The custom shortcut radio button was clicked, thus we have to restore + the custom shortcuts by calling those functions triggered by button + clicks. + """ + if not toggled: + return + self.onPrimaryPushButtonClicked(False) + self.onAlternatePushButtonClicked(False) + self.refreshShortcutList() + + def save(self): + """ + Save the shortcuts. **Note**, that we do not have to load the shortcuts, + as they are loaded in :class:`~openlp.core.utils.ActionList`. + """ + settings = QtCore.QSettings() + settings.beginGroup(u'shortcuts') + for category in self.action_list.categories: + # Check if the category is for internal use only. + if category.name is None: + continue + for action in category.actions: + if self.changedActions .has_key(action): + action.setShortcuts(self.changedActions[action]) + settings.setValue( + action.objectName(), QtCore.QVariant(action.shortcuts())) + settings.endGroup() + + def onClearPrimaryButtonClicked(self, toggled): + """ + Restore the defaults of this action. + """ + self.primaryPushButton.setChecked(False) + action = self._currentItemAction() + if action is None: + return + shortcuts = self._actionShortcuts(action) + new_shortcuts = [] + if len(action.defaultShortcuts) != 0: + new_shortcuts.append(action.defaultShortcuts[0]) + if len(shortcuts) == 2: + new_shortcuts.append(shortcuts[1]) + self.changedActions[action] = new_shortcuts + self.refreshShortcutList() + self.onCurrentItemChanged(self.treeWidget.currentItem()) + + def onClearAlternateButtonClicked(self, toggled): + """ + Restore the defaults of this action. + """ + self.alternatePushButton.setChecked(False) + action = self._currentItemAction() + if action is None: + return + shortcuts = self._actionShortcuts(action) + new_shortcuts = [] + if len(shortcuts) != 0: + new_shortcuts.append(shortcuts[0]) + if len(action.defaultShortcuts) == 2: + new_shortcuts.append(action.defaultShortcuts[1]) + self.changedActions[action] = new_shortcuts + self.refreshShortcutList() + self.onCurrentItemChanged(self.treeWidget.currentItem()) + + def _actionShortcuts(self, action): + """ + This returns the shortcuts for the given ``action``, which also includes + those shortcuts which are not saved yet but already assigned (as changes + are applied when closing the dialog). + """ + if self.changedActions.has_key(action): + return self.changedActions[action] + return action.shortcuts() + + def _currentItemAction(self, item=None): + """ + Returns the action of the given ``item``. If no item is given, we return + the action of the current item of the ``treeWidget``. + """ + if item is None: + item = self.treeWidget.currentItem() + if item is None: + return + return item.data(0, QtCore.Qt.UserRole).toPyObject() + + def _adjustButton(self, button, checked=None, enabled=None, text=None): + """ + Can be called to adjust more properties of the given ``button`` at once. + """ + # Set the text before checking the button, because this emits a signal. + if text is not None: + button.setText(text) + if checked is not None: + button.setChecked(checked) + if enabled is not None: + button.setEnabled(enabled) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 00202d8cc..b940b1e73 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -32,8 +32,9 @@ from PyQt4.phonon import Phonon from openlp.core.lib import OpenLPToolbar, Receiver, resize_image, \ ItemCapabilities, translate -from openlp.core.lib.ui import icon_action, UiStrings, shortcut_action +from openlp.core.lib.ui import UiStrings, shortcut_action from openlp.core.ui import HideMode, MainDisplay +from openlp.core.utils.actions import ActionList, CategoryOrder log = logging.getLogger(__name__) @@ -140,12 +141,16 @@ class SlideController(QtGui.QWidget): translate('OpenLP.SlideController', 'Previous Slide'), u':/slides/slide_previous.png', translate('OpenLP.SlideController', 'Move to previous'), - self.onSlideSelectedPrevious) + self.onSlideSelectedPrevious, + shortcuts=[QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp], + context=QtCore.Qt.WidgetWithChildrenShortcut) self.nextItem = self.toolbar.addToolbarButton( translate('OpenLP.SlideController', 'Next Slide'), u':/slides/slide_next.png', translate('OpenLP.SlideController', 'Move to next'), - self.onSlideSelectedNext) + self.onSlideSelectedNext, + shortcuts=[QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown], + context=QtCore.Qt.WidgetWithChildrenShortcut) self.toolbar.addToolbarSeparator(u'Close Separator') if self.isLive: self.hideMenu = QtGui.QToolButton(self.toolbar) @@ -154,16 +159,20 @@ class SlideController(QtGui.QWidget): self.toolbar.addToolbarWidget(u'Hide Menu', self.hideMenu) self.hideMenu.setMenu(QtGui.QMenu( translate('OpenLP.SlideController', 'Hide'), self.toolbar)) - self.blankScreen = icon_action(self.hideMenu, u'Blank Screen', - u':/slides/slide_blank.png', False) + self.blankScreen = shortcut_action(self.hideMenu, u'blankScreen', + [QtCore.Qt.Key_Period], self.onBlankDisplay, + u':/slides/slide_blank.png', False, UiStrings.LiveToolbar) self.blankScreen.setText( translate('OpenLP.SlideController', 'Blank Screen')) - self.themeScreen = icon_action(self.hideMenu, u'Blank Theme', - u':/slides/slide_theme.png', False) + self.themeScreen = shortcut_action(self.hideMenu, u'themeScreen', + [QtGui.QKeySequence(u'T')], self.onThemeDisplay, + u':/slides/slide_theme.png', False, UiStrings.LiveToolbar) self.themeScreen.setText( translate('OpenLP.SlideController', 'Blank to Theme')) - self.desktopScreen = icon_action(self.hideMenu, u'Desktop Screen', - u':/slides/slide_desktop.png', False) + self.desktopScreen = shortcut_action(self.hideMenu, + u'desktopScreen', [QtGui.QKeySequence(u'D')], + self.onHideDisplay, u':/slides/slide_desktop.png', False, + UiStrings.LiveToolbar) self.desktopScreen.setText( translate('OpenLP.SlideController', 'Show Desktop')) self.hideMenu.setDefaultAction(self.blankScreen) @@ -291,12 +300,6 @@ class SlideController(QtGui.QWidget): QtCore.QObject.connect(self.previewListWidget, QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected) if self.isLive: - QtCore.QObject.connect(self.blankScreen, - QtCore.SIGNAL(u'triggered(bool)'), self.onBlankDisplay) - QtCore.QObject.connect(self.themeScreen, - QtCore.SIGNAL(u'triggered(bool)'), self.onThemeDisplay) - QtCore.QObject.connect(self.desktopScreen, - QtCore.SIGNAL(u'triggered(bool)'), self.onHideDisplay) QtCore.QObject.connect(self.volumeSlider, QtCore.SIGNAL(u'sliderReleased()'), self.mediaVolume) QtCore.QObject.connect(Receiver.get_receiver(), @@ -362,33 +365,37 @@ class SlideController(QtGui.QWidget): QtCore.SIGNAL(u'config_screen_changed'), self.screenSizeChanged) def setPreviewHotkeys(self, parent=None): - actionList = self.parent.actionList - self.previousItem.setShortcuts([QtCore.Qt.Key_Up, 0]) - actionList.add_action(self.previousItem, u'Preview') - self.nextItem.setShortcuts([QtCore.Qt.Key_Down, 0]) - actionList.add_action(self.nextItem, u'Preview') + self.previousItem.setObjectName(u'previousItemPreview') + self.nextItem.setObjectName(u'nextItemPreview') + action_list = ActionList.get_instance() + action_list.add_category( + UiStrings.PreviewToolbar, CategoryOrder.standardToolbar) + action_list.add_action(self.previousItem, UiStrings.PreviewToolbar) + action_list.add_action(self.nextItem, UiStrings.PreviewToolbar) def setLiveHotkeys(self, parent=None): - actionList = self.parent.actionList - self.previousItem.setShortcuts([QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp]) - self.previousItem.setShortcutContext( - QtCore.Qt.WidgetWithChildrenShortcut) - actionList.add_action(self.previousItem, u'Live') - self.nextItem.setShortcuts([QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown]) - self.nextItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) - actionList.add_action(self.nextItem, u'Live') - self.previousService = shortcut_action(parent, - translate('OpenLP.SlideController', 'Previous Service'), - [QtCore.Qt.Key_Left, 0], self.servicePrevious) - actionList.add_action(self.previousService, u'Live') - self.nextService = shortcut_action(parent, - translate('OpenLP.SlideController', 'Next Service'), - [QtCore.Qt.Key_Right, 0], self.serviceNext) - actionList.add_action(self.nextService, u'Live') - self.escapeItem = shortcut_action(parent, - translate('OpenLP.SlideController', 'Escape Item'), - [QtCore.Qt.Key_Escape, 0], self.liveEscape) - actionList.add_action(self.escapeItem, u'Live') + self.previousItem.setObjectName(u'previousItemLive') + self.nextItem.setObjectName(u'nextItemLive') + action_list = ActionList.get_instance() + action_list.add_category( + UiStrings.LiveToolbar, CategoryOrder.standardToolbar) + action_list.add_action(self.previousItem, UiStrings.LiveToolbar) + action_list.add_action(self.nextItem, UiStrings.LiveToolbar) + self.previousService = shortcut_action(parent, u'previousService', + [QtCore.Qt.Key_Left], self.servicePrevious, UiStrings.LiveToolbar) + self.previousService.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) + self.previousService.setText( + translate('OpenLP.SlideController', 'Previous Service')) + self.nextService = shortcut_action(parent, 'nextService', + [QtCore.Qt.Key_Right], self.serviceNext, UiStrings.LiveToolbar) + self.nextService.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) + self.nextService.setText( + translate('OpenLP.SlideController', 'Next Service')) + self.escapeItem = shortcut_action(parent, 'escapeItem', + [QtCore.Qt.Key_Escape], self.liveEscape, UiStrings.LiveToolbar) + self.escapeItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) + self.escapeItem.setText( + translate('OpenLP.SlideController', 'Escape Item')) def liveEscape(self): self.display.setVisible(False) @@ -745,10 +752,12 @@ class SlideController(QtGui.QWidget): """ self.onBlankDisplay(False) - def onBlankDisplay(self, checked): + def onBlankDisplay(self, checked=None): """ Handle the blank screen button actions """ + if checked is None: + checked = self.blankScreen.isChecked() log.debug(u'onBlankDisplay %s' % checked) self.hideMenu.setDefaultAction(self.blankScreen) self.blankScreen.setChecked(checked) @@ -764,10 +773,12 @@ class SlideController(QtGui.QWidget): self.blankPlugin() self.updatePreview() - def onThemeDisplay(self, checked): + def onThemeDisplay(self, checked=None): """ Handle the Theme screen button """ + if checked is None: + checked = self.themeScreen.isChecked() log.debug(u'onThemeDisplay %s' % checked) self.hideMenu.setDefaultAction(self.themeScreen) self.blankScreen.setChecked(False) @@ -783,10 +794,12 @@ class SlideController(QtGui.QWidget): self.blankPlugin() self.updatePreview() - def onHideDisplay(self, checked): + def onHideDisplay(self, checked=None): """ Handle the Hide screen button """ + if checked is None: + checked = self.desktopScreen.isChecked() log.debug(u'onHideDisplay %s' % checked) self.hideMenu.setDefaultAction(self.desktopScreen) self.blankScreen.setChecked(False) diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index 6653e7e1d..3a3b3bb61 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -63,26 +63,19 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onGradientComboBoxCurrentIndexChanged) QtCore.QObject.connect(self.colorButton, - QtCore.SIGNAL(u'clicked()'), - self.onColorButtonClicked) + QtCore.SIGNAL(u'clicked()'), self.onColorButtonClicked) QtCore.QObject.connect(self.gradientStartButton, - QtCore.SIGNAL(u'clicked()'), - self.onGradientStartButtonClicked) + QtCore.SIGNAL(u'clicked()'), self.onGradientStartButtonClicked) QtCore.QObject.connect(self.gradientEndButton, - QtCore.SIGNAL(u'clicked()'), - self.onGradientEndButtonClicked) + QtCore.SIGNAL(u'clicked()'), self.onGradientEndButtonClicked) QtCore.QObject.connect(self.imageBrowseButton, - QtCore.SIGNAL(u'clicked()'), - self.onImageBrowseButtonClicked) + QtCore.SIGNAL(u'clicked()'), self.onImageBrowseButtonClicked) QtCore.QObject.connect(self.mainColorButton, - QtCore.SIGNAL(u'clicked()'), - self.onMainColorButtonClicked) + QtCore.SIGNAL(u'clicked()'), self.onMainColorButtonClicked) QtCore.QObject.connect(self.outlineColorButton, - QtCore.SIGNAL(u'clicked()'), - self.onOutlineColorButtonClicked) + QtCore.SIGNAL(u'clicked()'), self.onOutlineColorButtonClicked) QtCore.QObject.connect(self.shadowColorButton, - QtCore.SIGNAL(u'clicked()'), - self.onShadowColorButtonClicked) + QtCore.SIGNAL(u'clicked()'), self.onShadowColorButtonClicked) QtCore.QObject.connect(self.outlineCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onOutlineCheckCheckBoxStateChanged) @@ -90,8 +83,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): QtCore.SIGNAL(u'stateChanged(int)'), self.onShadowCheckCheckBoxStateChanged) QtCore.QObject.connect(self.footerColorButton, - QtCore.SIGNAL(u'clicked()'), - self.onFooterColorButtonClicked) + QtCore.SIGNAL(u'clicked()'), self.onFooterColorButtonClicked) QtCore.QObject.connect(self.mainPositionCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onMainPositionCheckBoxStateChanged) @@ -99,26 +91,23 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): QtCore.SIGNAL(u'stateChanged(int)'), self.onFooterPositionCheckBoxStateChanged) QtCore.QObject.connect(self, - QtCore.SIGNAL(u'currentIdChanged(int)'), - self.onCurrentIdChanged) + QtCore.SIGNAL(u'currentIdChanged(int)'), self.onCurrentIdChanged) QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'theme_line_count'), - self.updateLinesText) + QtCore.SIGNAL(u'theme_line_count'), self.updateLinesText) QtCore.QObject.connect(self.mainSizeSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.calculateLines) + QtCore.SIGNAL(u'valueChanged(int)'), self.calculateLines) QtCore.QObject.connect(self.lineSpacingSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.calculateLines) + QtCore.SIGNAL(u'valueChanged(int)'), self.calculateLines) QtCore.QObject.connect(self.outlineSizeSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.calculateLines) + QtCore.SIGNAL(u'valueChanged(int)'), self.calculateLines) QtCore.QObject.connect(self.shadowSizeSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.calculateLines) + QtCore.SIGNAL(u'valueChanged(int)'), self.calculateLines) QtCore.QObject.connect(self.mainFontComboBox, - QtCore.SIGNAL(u'activated(int)'), - self.calculateLines) + QtCore.SIGNAL(u'activated(int)'), self.calculateLines) + QtCore.QObject.connect(self.footerFontComboBox, + QtCore.SIGNAL(u'activated(int)'), self.updateTheme) + QtCore.QObject.connect(self.footerSizeSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), self.updateTheme) def setDefaults(self): """ @@ -389,7 +378,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): Handle the display and state of the Footer Area page. """ self.footerFontComboBox.setCurrentFont( - QtGui.QFont(self.theme.font_main_name)) + QtGui.QFont(self.theme.font_footer_name)) self.footerColorButton.setStyleSheet(u'background-color: %s' % self.theme.font_footer_color) self.setField(u'footerSizeSpinBox', diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index d033daeb3..81da6e021 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -445,6 +445,7 @@ class ThemeManager(QtGui.QWidget): files = SettingsManager.get_files(self.settingsSection, u'.png') if firstTime: self.firstTime() + files = SettingsManager.get_files(self.settingsSection, u'.png') # No themes have been found so create one if len(files) == 0: theme = ThemeXML() diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index 1b76d2198..1415c6810 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -28,7 +28,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, Receiver, translate from openlp.core.lib.theme import ThemeLevel -from openlp.core.lib.ui import UiStrings +from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box class ThemesTab(SettingsTab): """ @@ -185,12 +185,7 @@ class ThemesTab(SettingsTab): self.DefaultComboBox.clear() for theme in theme_list: self.DefaultComboBox.addItem(theme) - id = self.DefaultComboBox.findText( - self.global_theme, QtCore.Qt.MatchExactly) - if id == -1: - id = 0 # Not Found - self.global_theme = u'' - self.DefaultComboBox.setCurrentIndex(id) + find_and_set_in_combo_box(self.DefaultComboBox, self.global_theme) self.parent.renderManager.set_global_theme( self.global_theme, self.theme_level) if self.global_theme is not u'': @@ -206,4 +201,4 @@ class ThemesTab(SettingsTab): if not preview.isNull(): preview = preview.scaled(300, 255, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) - self.DefaultListView.setPixmap(preview) + self.DefaultListView.setPixmap(preview) \ No newline at end of file diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 3c639297e..1bc7037ae 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -495,7 +495,7 @@ def get_uno_instance(resolver): from languagemanager import LanguageManager from actions import ActionList -__all__ = [u'AppLocation', u'check_latest_version', u'add_actions', - u'get_filesystem_encoding', u'LanguageManager', u'ActionList', - u'get_web_page', u'file_is_unicode', u'string_is_unicode', +__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version', + u'add_actions', u'get_filesystem_encoding', u'LanguageManager', + u'ActionList', u'get_web_page', u'file_is_unicode', u'string_is_unicode', u'get_uno_command', u'get_uno_instance', u'delete_file'] diff --git a/openlp/core/utils/actions.py b/openlp/core/utils/actions.py index 41ae41f4b..0c4eee655 100644 --- a/openlp/core/utils/actions.py +++ b/openlp/core/utils/actions.py @@ -27,6 +27,8 @@ The :mod:`~openlp.core.utils.actions` module provides action list classes used by the shortcuts system. """ +from PyQt4 import QtCore, QtGui + class ActionCategory(object): """ The :class:`~openlp.core.utils.ActionCategory` class encapsulates a @@ -67,6 +69,7 @@ class CategoryActionList(object): Python 3 "next" method. """ if self.index >= len(self.actions): + self.index = 0 raise StopIteration else: self.index += 1 @@ -94,6 +97,12 @@ class CategoryActionList(object): self.actions.append((weight, action)) self.actions.sort(key=lambda act: act[0]) + def remove(self, remove_action): + for action in self.actions: + if action[1] == remove_action: + self.actions.remove(action) + return + class CategoryList(object): """ @@ -126,6 +135,7 @@ class CategoryList(object): Python 3 "next" method for iterator. """ if self.index >= len(self.categories): + self.index = 0 raise StopIteration else: self.index += 1 @@ -163,6 +173,11 @@ class CategoryList(object): self.categories.append(category) self.categories.sort(key=lambda cat: cat.weight) + def remove(self, name): + for category in self.categories: + if category.name == name: + self.categories.remove(category) + class ActionList(object): """ @@ -171,13 +186,101 @@ class ActionList(object): has a weight by which it is sorted when iterating through the list of actions or categories. """ + instance = None + def __init__(self): self.categories = CategoryList() - def add_action(self, action, category=u'Default', weight=None): + @staticmethod + def get_instance(): + if ActionList.instance is None: + ActionList.instance = ActionList() + return ActionList.instance + + def add_action(self, action, category=None, weight=None): + """ + Add an action to the list of actions. + + ``action`` + The action to add (QAction). + + ``category`` + The category this action belongs to. The category can be a QString + or python unicode string. **Note**, if the category is ``None``, the + category and its actions are being hidden in the shortcut dialog. + However, if they are added, it is possible to avoid assigning + shortcuts twice, which is important. + + ``weight`` + The weight specifies how important a category is. However, this only + has an impact on the order the categories are displayed. + """ + if category is not None: + category = unicode(category) if category not in self.categories: self.categories.append(category) + action.defaultShortcuts = action.shortcuts() if weight is None: self.categories[category].actions.append(action) else: self.categories[category].actions.add(action, weight) + if category is None: + # Stop here, as this action is not configurable. + return + # Load the shortcut from the config. + settings = QtCore.QSettings() + settings.beginGroup(u'shortcuts') + shortcuts = settings.value(action.objectName(), + QtCore.QVariant(action.shortcuts())).toStringList() + action.setShortcuts( + [QtGui.QKeySequence(shortcut) for shortcut in shortcuts]) + settings.endGroup() + + def remove_action(self, action, category=None): + """ + This removes an action from its category. Empty categories are + automatically removed. + + ``action`` + The QAction object to be removed. + + ``category`` + The name (unicode string) of the category, which contains the + action. Defaults to None. + """ + if category is not None: + category = unicode(category) + if category not in self.categories: + return + self.categories[category].actions.remove(action) + # Remove empty categories. + if len(self.categories[category].actions) == 0: + self.categories.remove(category) + + def add_category(self, name, weight): + """ + Add an empty category to the list of categories. This is ony convenient + for categories with a given weight. + + ``name`` + The category's name. + + ``weight`` + The category's weight (int). + """ + if name in self.categories: + # Only change the weight and resort the categories again. + for category in self.categories: + if category.name == name: + category.weight = weight + self.categories.categories.sort(key=lambda cat: cat.weight) + return + self.categories.add(name, weight) + + +class CategoryOrder(object): + """ + An enumeration class for category weights. + """ + standardMenu = -20 + standardToolbar = -10 diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index db0ba3b7e..7d6eac6e2 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -30,6 +30,8 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib.db import Manager +from openlp.core.lib.ui import icon_action, UiStrings +from openlp.core.utils.actions import ActionList from openlp.plugins.alerts.lib import AlertsManager, AlertsTab from openlp.plugins.alerts.lib.db import init_schema from openlp.plugins.alerts.forms import AlertForm @@ -58,9 +60,8 @@ class AlertsPlugin(Plugin): use it as their parent. """ log.info(u'add tools menu') - self.toolsAlertItem = QtGui.QAction(tools_menu) - self.toolsAlertItem.setIcon(build_icon(u':/plugins/plugin_alerts.png')) - self.toolsAlertItem.setObjectName(u'toolsAlertItem') + self.toolsAlertItem = icon_action(tools_menu, u'toolsAlertItem', + u':/plugins/plugin_alerts.png') self.toolsAlertItem.setText(translate('AlertsPlugin', '&Alert')) self.toolsAlertItem.setStatusTip( translate('AlertsPlugin', 'Show an alert message.')) @@ -74,6 +75,8 @@ class AlertsPlugin(Plugin): log.info(u'Alerts Initialising') Plugin.initialise(self) self.toolsAlertItem.setVisible(True) + action_list = ActionList.get_instance() + action_list.add_action(self.toolsAlertItem, UiStrings.Tools) self.liveController.alertTab = self.settings_tab def finalise(self): @@ -84,6 +87,8 @@ class AlertsPlugin(Plugin): self.manager.finalise() Plugin.finalise(self) self.toolsAlertItem.setVisible(False) + action_list = ActionList.get_instance() + action_list.remove_action(self.toolsAlertItem, u'Tools') def toggleAlertsState(self): self.alertsActive = not self.alertsActive diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index 4f677f211..aea732688 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -29,6 +29,8 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, StringContent, build_icon, translate +from openlp.core.lib.ui import base_action, UiStrings +from openlp.core.utils.actions import ActionList from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem log = logging.getLogger(__name__) @@ -50,6 +52,10 @@ class BiblePlugin(Plugin): self.manager = BibleManager(self) Plugin.initialise(self) self.importBibleItem.setVisible(True) + action_list = ActionList.get_instance() + action_list.add_action(self.importBibleItem, UiStrings.Import) + # Do not add the action to the list yet. + #action_list.add_action(self.exportBibleItem, UiStrings.Export) # Set to invisible until we can export bibles self.exportBibleItem.setVisible(False) @@ -60,25 +66,25 @@ class BiblePlugin(Plugin): log.info(u'Plugin Finalise') self.manager.finalise() Plugin.finalise(self) + action_list = ActionList.get_instance() + action_list.remove_action(self.importBibleItem, UiStrings.Import) self.importBibleItem.setVisible(False) + #action_list.remove_action(self.exportBibleItem, UiStrings.Export) self.exportBibleItem.setVisible(False) def addImportMenuItem(self, import_menu): - self.importBibleItem = QtGui.QAction(import_menu) - self.importBibleItem.setObjectName(u'importBibleItem') + self.importBibleItem = base_action(import_menu, u'importBibleItem') + self.importBibleItem.setText(translate('BiblesPlugin', '&Bible')) import_menu.addAction(self.importBibleItem) - self.importBibleItem.setText( - translate('BiblesPlugin', '&Bible')) # signals and slots QtCore.QObject.connect(self.importBibleItem, QtCore.SIGNAL(u'triggered()'), self.onBibleImportClick) self.importBibleItem.setVisible(False) def addExportMenuItem(self, export_menu): - self.exportBibleItem = QtGui.QAction(export_menu) - self.exportBibleItem.setObjectName(u'exportBibleItem') - export_menu.addAction(self.exportBibleItem) + self.exportBibleItem = base_action(export_menu, u'exportBibleItem') self.exportBibleItem.setText(translate('BiblesPlugin', '&Bible')) + export_menu.addAction(self.exportBibleItem) self.exportBibleItem.setVisible(False) def onBibleImportClick(self): diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index 117ffaf4c..35cd17c4b 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -85,8 +85,18 @@ class BibleImportForm(OpenLPWizard): """ OpenLPWizard.setupUi(self, image) QtCore.QObject.connect(self.formatComboBox, - QtCore.SIGNAL(u'currentIndexChanged(int)'), self.selectStack, - QtCore.SLOT(u'setCurrentIndex(int)')) + QtCore.SIGNAL(u'currentIndexChanged(int)'), + self.onCurrentIndexChanged) + + def onCurrentIndexChanged(self, index): + """ + Called when the format combo box's index changed. We have to check if + the import is available and accordingly to disable or enable the next + button. + """ + self.selectStack.setCurrentIndex(index) + next_button = self.button(QtGui.QWizard.NextButton) + next_button.setEnabled(BibleFormat.get_availability(index)) def customInit(self): """ diff --git a/openlp/plugins/bibles/lib/biblestab.py b/openlp/plugins/bibles/lib/biblestab.py index 7a631ad09..914377e35 100644 --- a/openlp/plugins/bibles/lib/biblestab.py +++ b/openlp/plugins/bibles/lib/biblestab.py @@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsTab, translate from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle +from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box log = logging.getLogger(__name__) @@ -48,108 +49,107 @@ class BiblesTab(SettingsTab): def setupUi(self): self.setObjectName(u'BiblesTab') SettingsTab.setupUi(self) - self.VerseDisplayGroupBox = QtGui.QGroupBox(self.leftColumn) - self.VerseDisplayGroupBox.setObjectName(u'VerseDisplayGroupBox') - self.VerseDisplayLayout = QtGui.QFormLayout(self.VerseDisplayGroupBox) - self.VerseDisplayLayout.setObjectName(u'VerseDisplayLayout') - self.NewChaptersCheckBox = QtGui.QCheckBox(self.VerseDisplayGroupBox) - self.NewChaptersCheckBox.setObjectName(u'NewChaptersCheckBox') - self.VerseDisplayLayout.addRow(self.NewChaptersCheckBox) - self.DisplayStyleLabel = QtGui.QLabel(self.VerseDisplayGroupBox) - self.DisplayStyleLabel.setObjectName(u'DisplayStyleLabel') - self.DisplayStyleComboBox = QtGui.QComboBox(self.VerseDisplayGroupBox) - self.DisplayStyleComboBox.addItems([u'', u'', u'', u'']) - self.DisplayStyleComboBox.setObjectName(u'DisplayStyleComboBox') - self.VerseDisplayLayout.addRow(self.DisplayStyleLabel, - self.DisplayStyleComboBox) - self.LayoutStyleLabel = QtGui.QLabel(self.VerseDisplayGroupBox) - self.LayoutStyleLabel.setObjectName(u'LayoutStyleLabel') - self.LayoutStyleComboBox = QtGui.QComboBox(self.VerseDisplayGroupBox) - self.LayoutStyleComboBox.setObjectName(u'LayoutStyleComboBox') - self.LayoutStyleComboBox.addItems([u'', u'', u'']) - self.VerseDisplayLayout.addRow(self.LayoutStyleLabel, - self.LayoutStyleComboBox) - self.BibleSecondCheckBox = QtGui.QCheckBox(self.VerseDisplayGroupBox) - self.BibleSecondCheckBox.setObjectName(u'BibleSecondCheckBox') - self.VerseDisplayLayout.addRow(self.BibleSecondCheckBox) - self.BibleThemeLabel = QtGui.QLabel(self.VerseDisplayGroupBox) - self.BibleThemeLabel.setObjectName(u'BibleThemeLabel') - self.BibleThemeComboBox = QtGui.QComboBox(self.VerseDisplayGroupBox) - self.BibleThemeComboBox.setSizeAdjustPolicy( + self.verseDisplayGroupBox = QtGui.QGroupBox(self.leftColumn) + self.verseDisplayGroupBox.setObjectName(u'verseDisplayGroupBox') + self.verseDisplayLayout = QtGui.QFormLayout(self.verseDisplayGroupBox) + self.verseDisplayLayout.setObjectName(u'verseDisplayLayout') + self.newChaptersCheckBox = QtGui.QCheckBox(self.verseDisplayGroupBox) + self.newChaptersCheckBox.setObjectName(u'newChaptersCheckBox') + self.verseDisplayLayout.addRow(self.newChaptersCheckBox) + self.displayStyleLabel = QtGui.QLabel(self.verseDisplayGroupBox) + self.displayStyleLabel.setObjectName(u'displayStyleLabel') + self.displayStyleComboBox = QtGui.QComboBox(self.verseDisplayGroupBox) + self.displayStyleComboBox.addItems([u'', u'', u'', u'']) + self.displayStyleComboBox.setObjectName(u'displayStyleComboBox') + self.verseDisplayLayout.addRow(self.displayStyleLabel, + self.displayStyleComboBox) + self.layoutStyleLabel = QtGui.QLabel(self.verseDisplayGroupBox) + self.layoutStyleLabel.setObjectName(u'layoutStyleLabel') + self.layoutStyleComboBox = QtGui.QComboBox(self.verseDisplayGroupBox) + self.layoutStyleComboBox.setObjectName(u'layoutStyleComboBox') + self.layoutStyleComboBox.addItems([u'', u'', u'']) + self.verseDisplayLayout.addRow(self.layoutStyleLabel, + self.layoutStyleComboBox) + self.bibleSecondCheckBox = QtGui.QCheckBox(self.verseDisplayGroupBox) + self.bibleSecondCheckBox.setObjectName(u'bibleSecondCheckBox') + self.verseDisplayLayout.addRow(self.bibleSecondCheckBox) + self.bibleThemeLabel = QtGui.QLabel(self.verseDisplayGroupBox) + self.bibleThemeLabel.setObjectName(u'BibleThemeLabel') + self.bibleThemeComboBox = QtGui.QComboBox(self.verseDisplayGroupBox) + self.bibleThemeComboBox.setSizeAdjustPolicy( QtGui.QComboBox.AdjustToMinimumContentsLength) - self.BibleThemeComboBox.setSizePolicy( + self.bibleThemeComboBox.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) - self.BibleThemeComboBox.addItem(u'') - self.BibleThemeComboBox.setObjectName(u'BibleThemeComboBox') - self.VerseDisplayLayout.addRow(self.BibleThemeLabel, - self.BibleThemeComboBox) - self.ChangeNoteLabel = QtGui.QLabel(self.VerseDisplayGroupBox) - self.ChangeNoteLabel.setWordWrap(True) - self.ChangeNoteLabel.setObjectName(u'ChangeNoteLabel') - self.VerseDisplayLayout.addRow(self.ChangeNoteLabel) - self.leftLayout.addWidget(self.VerseDisplayGroupBox) + self.bibleThemeComboBox.addItem(u'') + self.bibleThemeComboBox.setObjectName(u'BibleThemeComboBox') + self.verseDisplayLayout.addRow(self.bibleThemeLabel, + self.bibleThemeComboBox) + self.changeNoteLabel = QtGui.QLabel(self.verseDisplayGroupBox) + self.changeNoteLabel.setWordWrap(True) + self.changeNoteLabel.setObjectName(u'changeNoteLabel') + self.verseDisplayLayout.addRow(self.changeNoteLabel) + self.leftLayout.addWidget(self.verseDisplayGroupBox) self.leftLayout.addStretch() self.rightColumn.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) self.rightLayout.addStretch() # Signals and slots QtCore.QObject.connect( - self.NewChaptersCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), + self.newChaptersCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onNewChaptersCheckBoxChanged) QtCore.QObject.connect( - self.DisplayStyleComboBox, QtCore.SIGNAL(u'activated(int)'), + self.displayStyleComboBox, QtCore.SIGNAL(u'activated(int)'), self.onDisplayStyleComboBoxChanged) QtCore.QObject.connect( - self.BibleThemeComboBox, QtCore.SIGNAL(u'activated(int)'), + self.bibleThemeComboBox, QtCore.SIGNAL(u'activated(int)'), self.onBibleThemeComboBoxChanged) QtCore.QObject.connect( - self.LayoutStyleComboBox, QtCore.SIGNAL(u'activated(int)'), + self.layoutStyleComboBox, QtCore.SIGNAL(u'activated(int)'), self.onLayoutStyleComboBoxChanged) QtCore.QObject.connect( - self.BibleSecondCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), + self.bibleSecondCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onBibleSecondCheckBox) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList) def retranslateUi(self): - self.VerseDisplayGroupBox.setTitle( + self.verseDisplayGroupBox.setTitle( translate('BiblesPlugin.BiblesTab', 'Verse Display')) - self.NewChaptersCheckBox.setText( + self.newChaptersCheckBox.setText( translate('BiblesPlugin.BiblesTab', 'Only show new chapter numbers')) - self.LayoutStyleLabel.setText( + self.layoutStyleLabel.setText( translate('BiblesPlugin.BiblesTab', 'Layout style:')) - self.DisplayStyleLabel.setText( - translate('BiblesPlugin.BiblesTab', 'Display style:')) - self.BibleThemeLabel.setText( + self.displayStyleLabel.setText(UiStrings.DisplayStyle) + self.bibleThemeLabel.setText( translate('BiblesPlugin.BiblesTab', 'Bible theme:')) - self.LayoutStyleComboBox.setItemText(LayoutStyle.VersePerSlide, - translate('BiblesPlugin.BiblesTab', 'Verse Per Slide')) - self.LayoutStyleComboBox.setItemText(LayoutStyle.VersePerLine, - translate('BiblesPlugin.BiblesTab', 'Verse Per Line')) - self.LayoutStyleComboBox.setItemText(LayoutStyle.Continuous, - translate('BiblesPlugin.BiblesTab', 'Continuous')) - self.DisplayStyleComboBox.setItemText(DisplayStyle.NoBrackets, + self.layoutStyleComboBox.setItemText(LayoutStyle.VersePerSlide, + UiStrings.VersePerSlide) + self.layoutStyleComboBox.setItemText(LayoutStyle.VersePerLine, + UiStrings.VersePerLine) + self.layoutStyleComboBox.setItemText(LayoutStyle.Continuous, + UiStrings.Continuous) + self.displayStyleComboBox.setItemText(DisplayStyle.NoBrackets, translate('BiblesPlugin.BiblesTab', 'No Brackets')) - self.DisplayStyleComboBox.setItemText(DisplayStyle.Round, + self.displayStyleComboBox.setItemText(DisplayStyle.Round, translate('BiblesPlugin.BiblesTab', '( And )')) - self.DisplayStyleComboBox.setItemText(DisplayStyle.Curly, + self.displayStyleComboBox.setItemText(DisplayStyle.Curly, translate('BiblesPlugin.BiblesTab', '{ And }')) - self.DisplayStyleComboBox.setItemText(DisplayStyle.Square, + self.displayStyleComboBox.setItemText(DisplayStyle.Square, translate('BiblesPlugin.BiblesTab', '[ And ]')) - self.ChangeNoteLabel.setText(translate('BiblesPlugin.BiblesTab', + self.changeNoteLabel.setText(translate('BiblesPlugin.BiblesTab', 'Note:\nChanges do not affect verses already in the service.')) - self.BibleSecondCheckBox.setText( + self.bibleSecondCheckBox.setText( translate('BiblesPlugin.BiblesTab', 'Display second Bible verses')) def onBibleThemeComboBoxChanged(self): - self.bible_theme = self.BibleThemeComboBox.currentText() + self.bible_theme = self.bibleThemeComboBox.currentText() def onDisplayStyleComboBoxChanged(self): - self.display_style = self.DisplayStyleComboBox.currentIndex() + self.display_style = self.displayStyleComboBox.currentIndex() def onLayoutStyleComboBoxChanged(self): - self.layout_style = self.LayoutStyleComboBox.currentIndex() + self.layout_style = self.layoutStyleComboBox.currentIndex() def onNewChaptersCheckBoxChanged(self, check_state): self.show_new_chapters = False @@ -176,10 +176,10 @@ class BiblesTab(SettingsTab): settings.value(u'bible theme', QtCore.QVariant(u'')).toString()) self.second_bibles = settings.value( u'second bibles', QtCore.QVariant(True)).toBool() - self.NewChaptersCheckBox.setChecked(self.show_new_chapters) - self.DisplayStyleComboBox.setCurrentIndex(self.display_style) - self.LayoutStyleComboBox.setCurrentIndex(self.layout_style) - self.BibleSecondCheckBox.setChecked(self.second_bibles) + self.newChaptersCheckBox.setChecked(self.show_new_chapters) + self.displayStyleComboBox.setCurrentIndex(self.display_style) + self.layoutStyleComboBox.setCurrentIndex(self.layout_style) + self.bibleSecondCheckBox.setChecked(self.second_bibles) settings.endGroup() def save(self): @@ -204,14 +204,8 @@ class BiblesTab(SettingsTab): [u'Bible Theme', u'Song Theme'] """ - self.BibleThemeComboBox.clear() - self.BibleThemeComboBox.addItem(u'') + self.bibleThemeComboBox.clear() + self.bibleThemeComboBox.addItem(u'') for theme in theme_list: - self.BibleThemeComboBox.addItem(theme) - index = self.BibleThemeComboBox.findText( - unicode(self.bible_theme), QtCore.Qt.MatchExactly) - if index == -1: - # Not Found. - index = 0 - self.bible_theme = u'' - self.BibleThemeComboBox.setCurrentIndex(index) + self.bibleThemeComboBox.addItem(theme) + find_and_set_in_combo_box(self.bibleThemeComboBox, self.bible_theme) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 9c45b85f8..9e19d67bf 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -32,7 +32,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ translate from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.ui import UiStrings, add_widget_completer, \ - media_item_combo_box, critical_error_message_box + media_item_combo_box, critical_error_message_box, find_and_set_in_combo_box from openlp.plugins.bibles.forms import BibleImportForm from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \ VerseReferenceList, get_reference_match @@ -107,6 +107,12 @@ class BibleMediaItem(MediaManagerItem): translate('BiblesPlugin.MediaItem', 'Text Search')) ]) self.quickLayout.addRow(self.quickSearchLabel, self.quickSearchEdit) + self.quickLayoutLabel = QtGui.QLabel(self.quickTab) + self.quickLayoutLabel.setObjectName(u'quickClearLabel') + self.quickLayoutComboBox = media_item_combo_box(self.quickTab, + u'quickLayoutComboBox') + self.quickLayoutComboBox.addItems([u'', u'', u'']) + self.quickLayout.addRow(self.quickLayoutLabel, self.quickLayoutComboBox) self.quickClearLabel = QtGui.QLabel(self.quickTab) self.quickClearLabel.setObjectName(u'quickClearLabel') self.quickClearComboBox = media_item_combo_box(self.quickTab, @@ -211,6 +217,9 @@ class BibleMediaItem(MediaManagerItem): QtCore.SIGNAL(u'searchTypeChanged(int)'), self.updateAutoCompleter) QtCore.QObject.connect(self.quickVersionComboBox, QtCore.SIGNAL(u'activated(int)'), self.updateAutoCompleter) + QtCore.QObject.connect( + self.quickLayoutComboBox, QtCore.SIGNAL(u'activated(int)'), + self.onlayoutStyleComboBoxChanged) # Buttons QtCore.QObject.connect(self.advancedSearchButton, QtCore.SIGNAL(u'pressed()'), self.onAdvancedSearchButton) @@ -235,6 +244,7 @@ class BibleMediaItem(MediaManagerItem): self.advancedSecondComboBox.setVisible(False) self.quickSecondLabel.setVisible(False) self.quickSecondComboBox.setVisible(False) + self.quickLayoutComboBox.setCurrentIndex(self.settings.layout_style) def retranslateUi(self): log.debug(u'retranslateUi') @@ -270,11 +280,22 @@ class BibleMediaItem(MediaManagerItem): translate('BiblesPlugin.MediaItem', 'Clear')) self.advancedClearComboBox.addItem( translate('BiblesPlugin.MediaItem', 'Keep')) + self.quickLayoutLabel.setText(UiStrings.DisplayStyle) + self.quickLayoutComboBox.setItemText(LayoutStyle.VersePerSlide, + UiStrings.VersePerSlide) + self.quickLayoutComboBox.setItemText(LayoutStyle.VersePerLine, + UiStrings.VersePerLine) + self.quickLayoutComboBox.setItemText(LayoutStyle.Continuous, + UiStrings.Continuous) def initialise(self): log.debug(u'bible manager initialise') self.parent.manager.media = self self.loadBibles() + bible = QtCore.QSettings().value( + self.settingsSection + u'/quick bible', QtCore.QVariant( + self.quickVersionComboBox.currentText())).toString() + find_and_set_in_combo_box(self.quickVersionComboBox, bible) self.updateAutoCompleter() self.configUpdated() log.debug(u'bible manager initialise complete') @@ -299,23 +320,28 @@ class BibleMediaItem(MediaManagerItem): bibles = self.parent.manager.get_bibles().keys() bibles.sort() # Load the bibles into the combo boxes. - first = True for bible in bibles: if bible: self.quickVersionComboBox.addItem(bible) self.quickSecondComboBox.addItem(bible) self.advancedVersionComboBox.addItem(bible) self.advancedSecondComboBox.addItem(bible) - if first: - first = False - self.initialiseBible(bible) + # set the default value + bible = QtCore.QSettings().value( + self.settingsSection + u'/advanced bible', + QtCore.QVariant(u'')).toString() + if bible in bibles: + find_and_set_in_combo_box(self.advancedVersionComboBox, bible) + self.initialiseAdvancedBible(unicode(bible)) + elif len(bibles): + self.initialiseAdvancedBible(bibles[0]) def reloadBibles(self): log.debug(u'Reloading Bibles') self.parent.manager.reload_bibles() self.loadBibles() - def initialiseBible(self, bible): + def initialiseAdvancedBible(self, bible): """ This initialises the given bible, which means that its book names and their chapter numbers is added to the combo boxes on the @@ -325,7 +351,7 @@ class BibleMediaItem(MediaManagerItem): ``bible`` The bible to initialise (unicode). """ - log.debug(u'initialiseBible %s', bible) + log.debug(u'initialiseAdvancedBible %s', bible) book_data = self.parent.manager.get_books(bible) self.advancedBookComboBox.clear() first = True @@ -361,6 +387,8 @@ class BibleMediaItem(MediaManagerItem): completion depends on the bible. It is only updated when we are doing a reference search, otherwise the auto completion list is removed. """ + QtCore.QSettings().setValue(self.settingsSection + u'/quick bible', + QtCore.QVariant(self.quickVersionComboBox.currentText())) books = [] # We have to do a 'Reference Search'. if self.quickSearchEdit.currentSearchType() == BibleSearch.Reference: @@ -368,12 +396,14 @@ class BibleMediaItem(MediaManagerItem): bible = unicode(self.quickVersionComboBox.currentText()) if bible: book_data = bibles[bible].get_books() - books = [book.name for book in book_data] + books = [book.name + u' ' for book in book_data] books.sort() add_widget_completer(books, self.quickSearchEdit) def onAdvancedVersionComboBox(self): - self.initialiseBible( + QtCore.QSettings().setValue(self.settingsSection + u'/advanced bible', + QtCore.QVariant(self.advancedVersionComboBox.currentText())) + self.initialiseAdvancedBible( unicode(self.advancedVersionComboBox.currentText())) def onAdvancedBookComboBox(self): @@ -805,3 +835,11 @@ class BibleMediaItem(MediaManagerItem): if self.settings.display_style == DisplayStyle.Square: return u'{su}[%s]{/su}' % verse_text return u'{su}%s{/su}' % verse_text + + def onlayoutStyleComboBoxChanged(self): + self.settings.layout_style = self.quickLayoutComboBox.currentIndex() + self.settings.layoutStyleComboBox.setCurrentIndex( + self.settings.layout_style) + QtCore.QSettings().setValue( + self.settingsSection + u'/verse layout style', + QtCore.QVariant(self.settings.layout_style)) diff --git a/openlp/plugins/bibles/lib/versereferencelist.py b/openlp/plugins/bibles/lib/versereferencelist.py index bc28f2570..bab6d7e11 100644 --- a/openlp/plugins/bibles/lib/versereferencelist.py +++ b/openlp/plugins/bibles/lib/versereferencelist.py @@ -96,4 +96,7 @@ class VerseReferenceList(object): version[u'copyright']) if version[u'permission'].strip(): result = result + u', ' + version[u'permission'] + result = result.rstrip() + if result.endswith(u','): + return result[:len(result)-1] return result diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index f81bd4c7d..9312b5ddd 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -29,7 +29,7 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, translate -from openlp.core.lib.ui import critical_error_message_box +from openlp.core.lib.ui import critical_error_message_box, find_and_set_in_combo_box from openlp.plugins.custom.lib import CustomXMLBuilder, CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide from editcustomdialog import Ui_CustomEditDialog @@ -98,11 +98,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): for slide in slideList: self.slideListView.addItem(slide[1]) theme = self.customSlide.theme_name - id = self.themeComboBox.findText(theme, QtCore.Qt.MatchExactly) - # No theme match - if id == -1: - id = 0 - self.themeComboBox.setCurrentIndex(id) + find_and_set_in_combo_box(self.themeComboBox, theme) # If not preview hide the preview button. self.previewButton.setVisible(False) if preview: @@ -265,4 +261,4 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): message=translate('CustomPlugin.EditCustomForm', 'You need to add at least one slide')) return False - return True + return True \ No newline at end of file diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index 3c7bdcc33..8d48d98a3 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -105,7 +105,7 @@ class PresentationDocument(object): Loads the presentation and starts it ``presentation`` - The file name of the presentations to the run. + The file name of the presentations to the run. Returns False if the file could not be opened """ diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 2f21e57cd..85294d92b 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, translate from openlp.core.lib.ui import UiStrings, add_widget_completer, \ - critical_error_message_box + critical_error_message_box, find_and_set_in_combo_box from openlp.plugins.songs.forms import EditVerseForm from openlp.plugins.songs.lib import SongXML, VerseType, clean_song from openlp.plugins.songs.lib.db import Book, Song, Author, Topic @@ -208,20 +208,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.alternativeEdit.setText(u'') if self.song.song_book_id != 0: book_name = self.manager.get_object(Book, self.song.song_book_id) - id = self.songBookComboBox.findText( - unicode(book_name.name), QtCore.Qt.MatchExactly) - if id == -1: - # Not Found - id = 0 - self.songBookComboBox.setCurrentIndex(id) + find_and_set_in_combo_box(self.songBookComboBox, unicode(book_name.name)) if self.song.theme_name: - id = self.themeComboBox.findText( - unicode(self.song.theme_name), QtCore.Qt.MatchExactly) - if id == -1: - # Not Found - id = 0 - self.song.theme_name = None - self.themeComboBox.setCurrentIndex(id) + find_and_set_in_combo_box(self.themeComboBox, unicode(self.song.theme_name)) if self.song.copyright: self.copyrightEdit.setText(self.song.copyright) else: @@ -790,4 +779,4 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.song.verse_order) except: log.exception(u'Problem processing song Lyrics \n%s', - sxml.dump_xml()) + sxml.dump_xml()) \ No newline at end of file diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 6d20c8f41..468d2f341 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -66,7 +66,17 @@ class SongImportForm(OpenLPWizard): self.formatStack.setCurrentIndex(0) QtCore.QObject.connect(self.formatComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), - self.formatStack.setCurrentIndex) + self.onCurrentIndexChanged) + + def onCurrentIndexChanged(self, index): + """ + Called when the format combo box's index changed. We have to check if + the import is available and accordingly to disable or enable the next + button. + """ + self.formatStack.setCurrentIndex(index) + next_button = self.button(QtGui.QWizard.NextButton) + next_button.setEnabled(SongFormat.get_availability(index)) def customInit(self): """ diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index f4803d653..e2882ed29 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -283,19 +283,20 @@ class SongMediaItem(MediaManagerItem): self.remoteTriggered = None self.remoteSong = -1 - def onRemoteEdit(self, songid): + def onRemoteEdit(self, message): """ Called by ServiceManager or SlideController by event passing the Song Id in the payload along with an indicator to say which type of display is required. """ - log.debug(u'onRemoteEdit %s' % songid) - fields = songid.split(u':') - valid = self.parent.manager.get_object(Song, fields[1]) + log.debug(u'onRemoteEdit %s' % message) + remote_type, song_id = message.split(u':') + song_id = int(song_id) + valid = self.parent.manager.get_object(Song, song_id) if valid: - self.remoteSong = fields[1] - self.remoteTriggered = fields[0] - self.edit_song_form.loadSong(fields[1], (fields[0] == u'P')) + self.remoteSong = song_id + self.remoteTriggered = remote_type + self.edit_song_form.loadSong(song_id, (remote_type == u'P')) self.edit_song_form.exec_() def onEditClick(self): diff --git a/openlp/plugins/songs/lib/oooimport.py b/openlp/plugins/songs/lib/oooimport.py index c9c05907e..2ab66820c 100644 --- a/openlp/plugins/songs/lib/oooimport.py +++ b/openlp/plugins/songs/lib/oooimport.py @@ -39,12 +39,8 @@ if os.name == u'nt': PAGE_AFTER = 5 PAGE_BOTH = 6 else: - try: - import uno - from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER, \ - PAGE_BOTH - except ImportError: - pass + import uno + from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER, PAGE_BOTH class OooImport(SongImport): """ diff --git a/openlp/plugins/songs/lib/openlyricsexport.py b/openlp/plugins/songs/lib/openlyricsexport.py index d3367bfa9..59b720d3e 100644 --- a/openlp/plugins/songs/lib/openlyricsexport.py +++ b/openlp/plugins/songs/lib/openlyricsexport.py @@ -73,6 +73,8 @@ class OpenLyricsExport(object): u', '.join([author.display_name for author in song.authors])) filename = re.sub( r'[/\\?*|<>\[\]":<>+%]+', u'_', filename).strip(u'_') - tree.write(os.path.join(self.save_path, filename), + # Pass a file object, because lxml does not cope with some special + # characters in the path (see lp:757673 and lp:744337). + tree.write(open(os.path.join(self.save_path, filename), u'w'), encoding=u'utf-8', xml_declaration=True, pretty_print=True) return True diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py index 208ef3e52..c29abc0b5 100644 --- a/openlp/plugins/songs/lib/openlyricsimport.py +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -63,7 +63,9 @@ class OpenLyricsImport(SongImport): self.import_wizard.incrementProgressBar( WizardStrings.ImportingType % os.path.basename(file_path)) try: - parsed_file = etree.parse(file_path, parser) + # Pass a file object, because lxml does not cope with some + # special characters in the path (see lp:757673 and lp:744337). + parsed_file = etree.parse(open(file_path, u'r'), parser) xml = unicode(etree.tostring(parsed_file)) if self.openLyrics.xml_to_song(xml) is None: log.debug(u'File could not be imported: %s' % file_path) diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 1260a832b..af50f3f94 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -33,7 +33,8 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, StringContent, build_icon, translate, \ Receiver from openlp.core.lib.db import Manager -from openlp.core.lib.ui import UiStrings +from openlp.core.lib.ui import UiStrings, base_action, icon_action +from openlp.core.utils.actions import ActionList from openlp.plugins.songs.lib import clean_song, SongMediaItem, SongsTab from openlp.plugins.songs.lib.db import init_schema, Song from openlp.plugins.songs.lib.importer import SongFormat @@ -65,6 +66,10 @@ class SongsPlugin(Plugin): log.info(u'Songs Initialising') Plugin.initialise(self) self.toolsReindexItem.setVisible(True) + action_list = ActionList.get_instance() + action_list.add_action(self.SongImportItem, UiStrings.Import) + action_list.add_action(self.SongExportItem, UiStrings.Export) + action_list.add_action(self.toolsReindexItem, UiStrings.Tools) self.mediaItem.displayResultsSong( self.manager.get_all_objects(Song, order_by_ref=Song.search_title)) @@ -78,10 +83,8 @@ class SongsPlugin(Plugin): use it as their parent. """ # Main song import menu item - will eventually be the only one - self.SongImportItem = QtGui.QAction(import_menu) - self.SongImportItem.setObjectName(u'SongImportItem') - self.SongImportItem.setText(translate( - 'SongsPlugin', '&Song')) + self.SongImportItem = base_action(import_menu, u'SongImportItem') + self.SongImportItem.setText(translate('SongsPlugin', '&Song')) self.SongImportItem.setToolTip(translate('SongsPlugin', 'Import songs using the import wizard.')) import_menu.addAction(self.SongImportItem) @@ -99,10 +102,8 @@ class SongsPlugin(Plugin): use it as their parent. """ # Main song import menu item - will eventually be the only one - self.SongExportItem = QtGui.QAction(export_menu) - self.SongExportItem.setObjectName(u'SongExportItem') - self.SongExportItem.setText(translate( - 'SongsPlugin', '&Song')) + self.SongExportItem = base_action(export_menu, u'SongExportItem') + self.SongExportItem.setText(translate('SongsPlugin', '&Song')) self.SongExportItem.setToolTip(translate('SongsPlugin', 'Exports songs using the export wizard.')) export_menu.addAction(self.SongExportItem) @@ -120,9 +121,8 @@ class SongsPlugin(Plugin): use it as their parent. """ log.info(u'add tools menu') - self.toolsReindexItem = QtGui.QAction(tools_menu) - self.toolsReindexItem.setIcon(build_icon(u':/plugins/plugin_songs.png')) - self.toolsReindexItem.setObjectName(u'toolsReindexItem') + self.toolsReindexItem = icon_action(tools_menu, u'toolsReindexItem', + u':/plugins/plugin_songs.png') self.toolsReindexItem.setText( translate('SongsPlugin', '&Re-index Songs')) self.toolsReindexItem.setStatusTip( @@ -259,4 +259,8 @@ class SongsPlugin(Plugin): log.info(u'Songs Finalising') self.manager.finalise() self.toolsReindexItem.setVisible(False) + action_list = ActionList.get_instance() + action_list.remove_action(self.SongImportItem, UiStrings.Import) + action_list.remove_action(self.SongExportItem, UiStrings.Export) + action_list.remove_action(self.toolsReindexItem, UiStrings.Tools) Plugin.finalise(self) diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 8ff40373a..5f21451b6 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -32,6 +32,8 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, \ translate from openlp.core.lib.db import Manager +from openlp.core.lib.ui import base_action, shortcut_action, UiStrings +from openlp.core.utils.actions import ActionList from openlp.plugins.songusage.forms import SongUsageDetailForm, \ SongUsageDeleteForm from openlp.plugins.songusage.lib.db import init_schema, SongUsageItem @@ -63,30 +65,25 @@ class SongUsagePlugin(Plugin): self.SongUsageMenu.setObjectName(u'SongUsageMenu') self.SongUsageMenu.setTitle(translate( 'SongUsagePlugin', '&Song Usage Tracking')) - #SongUsage Delete - self.SongUsageDelete = QtGui.QAction(tools_menu) + # SongUsage Delete + self.SongUsageDelete = base_action(tools_menu, u'SongUsageDelete') self.SongUsageDelete.setText(translate('SongUsagePlugin', '&Delete Tracking Data')) self.SongUsageDelete.setStatusTip(translate('SongUsagePlugin', 'Delete song usage data up to a specified date.')) - self.SongUsageDelete.setObjectName(u'SongUsageDelete') - #SongUsage Report - self.SongUsageReport = QtGui.QAction(tools_menu) + # SongUsage Report + self.SongUsageReport = base_action(tools_menu, u'SongUsageReport') self.SongUsageReport.setText( translate('SongUsagePlugin', '&Extract Tracking Data')) self.SongUsageReport.setStatusTip( translate('SongUsagePlugin', 'Generate a report on song usage.')) - self.SongUsageReport.setObjectName(u'SongUsageReport') - #SongUsage activation - self.SongUsageStatus = QtGui.QAction(tools_menu) - self.SongUsageStatus.setCheckable(True) - self.SongUsageStatus.setChecked(False) + # SongUsage activation + self.SongUsageStatus = shortcut_action(tools_menu, u'SongUsageStatus', + [QtCore.Qt.Key_F4], self.toggleSongUsageState, checked=False) self.SongUsageStatus.setText(translate( 'SongUsagePlugin', 'Toggle Tracking')) self.SongUsageStatus.setStatusTip(translate('SongUsagePlugin', 'Toggle the tracking of song usage.')) - self.SongUsageStatus.setShortcut(u'F4') - self.SongUsageStatus.setObjectName(u'SongUsageStatus') #Add Menus together self.toolsMenu.addAction(self.SongUsageMenu.menuAction()) self.SongUsageMenu.addAction(self.SongUsageStatus) @@ -97,9 +94,6 @@ class SongUsagePlugin(Plugin): QtCore.QObject.connect(self.SongUsageStatus, QtCore.SIGNAL(u'visibilityChanged(bool)'), self.SongUsageStatus.setChecked) - QtCore.QObject.connect(self.SongUsageStatus, - QtCore.SIGNAL(u'triggered(bool)'), - self.toggleSongUsageState) QtCore.QObject.connect(self.SongUsageDelete, QtCore.SIGNAL(u'triggered()'), self.onSongUsageDelete) QtCore.QObject.connect(self.SongUsageReport, @@ -116,6 +110,13 @@ class SongUsagePlugin(Plugin): self.settingsSection + u'/active', QtCore.QVariant(False)).toBool() self.SongUsageStatus.setChecked(self.SongUsageActive) + action_list = ActionList.get_instance() + action_list.add_action(self.SongUsageDelete, + translate('SongUsagePlugin', 'Song Usage')) + action_list.add_action(self.SongUsageReport, + translate('SongUsagePlugin', 'Song Usage')) + action_list.add_action(self.SongUsageStatus, + translate('SongUsagePlugin', 'Song Usage')) if self.manager is None: self.manager = Manager(u'songusage', init_schema) self.SongUsagedeleteform = SongUsageDeleteForm(self.manager, @@ -131,6 +132,13 @@ class SongUsagePlugin(Plugin): self.manager.finalise() Plugin.finalise(self) self.SongUsageMenu.menuAction().setVisible(False) + action_list = ActionList.get_instance() + action_list.remove_action(self.SongUsageDelete, + translate('SongUsagePlugin', 'Song Usage')) + action_list.remove_action(self.SongUsageReport, + translate('SongUsagePlugin', 'Song Usage')) + action_list.remove_action(self.SongUsageStatus, + translate('SongUsagePlugin', 'Song Usage')) #stop any events being processed self.SongUsageActive = False diff --git a/resources/forms/shortcutlistdialog.ui b/resources/forms/shortcutlistdialog.ui index 519925560..9a5c599d1 100644 --- a/resources/forms/shortcutlistdialog.ui +++ b/resources/forms/shortcutlistdialog.ui @@ -41,35 +41,35 @@ - + + + 0 + 8 - - 0 - - + - Default: None + Default: true - - + + + + Custom: + + + + + 8 - - - - Custom: - - - @@ -83,7 +83,7 @@ - :/system/system_settings.png:/system/system_settings.png + :/system/system_configure_shortcuts.png:/system/system_configure_shortcuts.png true @@ -110,21 +110,51 @@ + + + + + + 8 + - - - Qt::Horizontal + + + None - - - 40 - 20 - + + + :/system/system_configure_shortcuts.png:/system/system_configure_shortcuts.png - + + + + + + + + + + :/system/clear_shortcut.png:/system/clear_shortcut.png + + + + + + Ctrl+V + + + + + + + Shift+Ins + + +