← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~googol-hush/openlp/tweaks into lp:openlp

 

Andreas Preikschat has proposed merging lp:~googol-hush/openlp/tweaks into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)
Related bugs:
  Bug #739779 in OpenLP: "No keyboard shortcut for blank"
  https://bugs.launchpad.net/openlp/+bug/739779

For more details, see:
https://code.launchpad.net/~googol-hush/openlp/tweaks/+merge/55945

Hello

I finished implementing shortcuts, this includes:
- changing shortcuts,
- saving/loading them to the config, so that they will be restored

Things I have done to achieve this:
- tweaked the icon_action, base_action, ... to automatically add the action to the list of actions if a category is specified
- gave the buttons in the dialog functionality (I also removed things there)
- changed the action all over the application to work correctly with the new standard actions (icon_action, ...)

Also fixed bug #739779.

Things still to be done:
- It is not possible to assign shortcuts to two actions when they are not valid for the whole application (i.e. Live Controller/Preview Controller)
- The dialog closes on ESC even when we are capturing a shortcut
- It seems that previousItem and nextItem actions are not properly saved to the config (not sure about this)
- the dialog might be reworked. I am not sure, if it is usable enough. If you have passion for creating UI I hope that this will become teamwork ;-)

I hope I have not forgotten anything...

Note, I am proposing for merging, because I do not have time at the moment and as it is a quite large change I do not want that too much times passes till it is completely finished. And I might be able to fix things up, while you are reviewing...

Cheers
-- 
https://code.launchpad.net/~googol-hush/openlp/tweaks/+merge/55945
Your team OpenLP Core is requested to review the proposed merge of lp:~googol-hush/openlp/tweaks into lp:openlp.
=== modified file 'openlp/core/lib/searchedit.py'
--- openlp/core/lib/searchedit.py	2011-03-24 19:04:02 +0000
+++ openlp/core/lib/searchedit.py	2011-04-01 15:02:30 +0000
@@ -29,6 +29,7 @@
 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,7 @@
         menu = QtGui.QMenu(self)
         first = None
         for identifier, icon, title in items:
-            action = QtGui.QAction(build_icon(icon), title, menu)
+            action = icon_action(menu, title, icon)
             action.setData(QtCore.QVariant(identifier))
             menu.addAction(action)
             QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'),

=== modified file 'openlp/core/lib/toolbar.py'
--- openlp/core/lib/toolbar.py	2011-03-24 19:04:02 +0000
+++ openlp/core/lib/toolbar.py	2011-04-01 15:02:30 +0000
@@ -51,8 +51,7 @@
         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,11 +73,8 @@
             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
@@ -103,8 +99,9 @@
             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):

=== modified file 'openlp/core/lib/ui.py'
--- openlp/core/lib/ui.py	2011-03-27 16:30:40 +0000
+++ openlp/core/lib/ui.py	2011-04-01 15:02:30 +0000
@@ -31,6 +31,7 @@
 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__)
 
@@ -238,42 +239,58 @@
         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:
+        ActionList.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):
     """
     Return a shortcut enabled action.
     """
-    action = QtGui.QAction(text, parent)
+    if icon is not None:
+        action = icon_action(parent, name, icon, checked, category)
+    elif checked is not None:
+        action = checkable_action(parent, name, checked, category)
+    else:
+        action = base_action(parent, name, category)
     action.setShortcuts(shortcuts)
-    action.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
+    action.setShortcutContext(QtCore.Qt.WindowShortcut)
+    # We have to save the default shortcut again, as the action's shortcut was
+    # set after adding the shortcut to the action list.
+    action.defaultShortcuts = action.shortcuts()
     QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), function)
     return action
 

=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py	2011-03-30 18:52:58 +0000
+++ openlp/core/ui/mainwindow.py	2011-04-01 15:02:30 +0000
@@ -33,12 +33,12 @@
 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
 
 log = logging.getLogger(__name__)
 
@@ -161,74 +161,75 @@
         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')
+        self.FileNewItem = shortcut_action(mainWindow, u'FileNewItem',
+            [QtGui.QKeySequence(u'Ctrl+N')],
+            self.ServiceManagerContents.onNewServiceClicked,
+            u':/general/general_new.png', category=u'File')
+        self.FileOpenItem = shortcut_action(mainWindow, u'FileOpenItem',
+            [QtGui.QKeySequence(u'Ctrl+O')],
+            self.ServiceManagerContents.onLoadServiceClicked,
+            u':/general/general_open.png', category=u'File')
+        self.FileSaveItem = shortcut_action(mainWindow, u'FileSaveItem',
+            [QtGui.QKeySequence(u'Ctrl+S')],
+            self.ServiceManagerContents.saveFile,
+            u':/general/general_save.png', category=u'File')
+        self.FileSaveAsItem = shortcut_action(mainWindow, u'FileSaveAsItem',
+            [QtGui.QKeySequence(u'Ctrl+Shift+S')],
+            self.ServiceManagerContents.saveFileAs, category=u'File')
+        self.printServiceOrderItem = shortcut_action(mainWindow,
+            u'printServiceItem', [QtGui.QKeySequence(u'Ctrl+P')],
+            self.ServiceManagerContents.printServiceOrder,  category=u'File')
+        self.FileExitItem = shortcut_action(mainWindow, u'FileExitItem',
+            [QtGui.QKeySequence(u'Alt+F4')], mainWindow.close,
+            u':/system/system_exit.png', category=u'File')
+        self.ImportThemeItem = base_action(
+            mainWindow, u'ImportThemeItem', u'Import')
+        self.ImportLanguageItem = base_action(
+            mainWindow, u'ImportLanguageItem')#, u'Import')
+        self.ExportThemeItem = base_action(
+            mainWindow, u'ExportThemeItem', u'Export')
+        self.ExportLanguageItem = base_action(
+            mainWindow, u'ExportLanguageItem')#, u'Export')
+        self.ViewMediaManagerItem = shortcut_action(mainWindow,
+            u'ViewMediaManagerItem', [QtGui.QKeySequence(u'F8')],
+            self.toggleMediaManager, u':/system/system_mediamanager.png',
+            self.mediaManagerDock.isVisible(), u'View')
+        self.ViewThemeManagerItem = shortcut_action(mainWindow,
+            u'ViewThemeManagerItem', [QtGui.QKeySequence(u'F10')],
+            self.toggleThemeManager,  u':/system/system_thememanager.png',
+            self.themeManagerDock.isVisible(), u'View')
+        self.ViewServiceManagerItem = shortcut_action(mainWindow,
+            u'ViewServiceManagerItem', [QtGui.QKeySequence(u'F9')],
+            self.toggleServiceManager, u':/system/system_servicemanager.png',
+            self.serviceManagerDock.isVisible(), u'View')
+        self.ViewPreviewPanel = shortcut_action(mainWindow,
+            u'ViewPreviewPanel', [QtGui.QKeySequence(u'F11')],
+            self.setPreviewPanelVisibility, checked=previewVisible, category=u'View')
+        self.ViewLivePanel = shortcut_action(mainWindow, u'ViewLivePanel',
+            [QtGui.QKeySequence(u'F12')], self.setLivePanelVisibility,
+            checked=liveVisible, category=u'View')
+        self.ModeDefaultItem = checkable_action(
+            mainWindow, u'ModeDefaultItem', category=u'View Mode')
+        self.ModeSetupItem = checkable_action(
+            mainWindow, u'ModeLiveItem', category=u'View Mode')
+        self.ModeLiveItem = checkable_action(
+            mainWindow, u'ModeLiveItem', True, u'View Mode')
         self.ModeGroup = QtGui.QActionGroup(mainWindow)
         self.ModeGroup.addAction(self.ModeDefaultItem)
         self.ModeGroup.addAction(self.ModeSetupItem)
         self.ModeGroup.addAction(self.ModeLiveItem)
         self.ModeDefaultItem.setChecked(True)
         self.ToolsAddToolItem = icon_action(mainWindow, u'ToolsAddToolItem',
-            u':/tools/tools_add.png')
-        mainWindow.actionList.add_action(self.ToolsAddToolItem, u'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':/tools/tools_add.png', category=u'Tools')
+        self.ToolsOpenDataFolder = icon_action(mainWindow, u'ToolsOpenDataFolder',
+            u':/general/general_open.png', category=u'Tools')
+        self.settingsPluginListItem = shortcut_action(mainWindow,
+            u'settingsPluginListItem', [QtGui.QKeySequence(u'Alt+F7')],
+            self.onPluginItemClicked, u':/system/settings_plugin_list.png',
+            category=u'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 +242,23 @@
             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=u'Settings')
         self.DisplayTagItem = icon_action(mainWindow,
-            u'DisplayTagItem', u':/system/tag_editor.png')
+            u'DisplayTagItem', u':/system/tag_editor.png', category=u'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=u'Settings')
         self.HelpDocumentationItem = icon_action(mainWindow,
-            u'HelpDocumentationItem', u':/system/system_help_contents.png')
+            u'HelpDocumentationItem', u':/system/system_help_contents.png',
+            category=None)#u'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=u'Help')
+        self.HelpOnlineHelpItem = base_action(
+            mainWindow, u'HelpOnlineHelpItem', category=u'Help')
+        self.helpWebSiteItem = base_action(
+            mainWindow, u'helpWebSiteItem', category=u'Help')
         add_actions(self.FileImportMenu,
             (self.ImportThemeItem, self.ImportLanguageItem))
         add_actions(self.FileExportMenu,
@@ -294,14 +294,11 @@
         # 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 +326,27 @@
         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 +367,39 @@
             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 +441,6 @@
     """
     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 +457,6 @@
         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 +481,6 @@
         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 +494,14 @@
             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 +724,8 @@
         """
         Show the shortcuts dialog
         """
-        self.shortcutForm.exec_(self.actionList)
+        if self.shortcutForm.exec_():
+            self.shortcutForm.save()
 
     def onModeDefaultItemClicked(self):
         """
@@ -928,19 +872,16 @@
             unicode(translate('OpenLP.MainWindow', 'Default Theme: %s')) %
                 theme)
 
-    def toggleMediaManager(self, visible):
-        if self.mediaManagerDock.isVisible() != visible:
-            self.mediaManagerDock.setVisible(visible)
-
-    def toggleServiceManager(self, visible):
-        if self.serviceManagerDock.isVisible() != visible:
-            self.serviceManagerDock.setVisible(visible)
-
-    def toggleThemeManager(self, visible):
-        if self.themeManagerDock.isVisible() != visible:
-            self.themeManagerDock.setVisible(visible)
-
-    def setPreviewPanelVisibility(self, visible):
+    def toggleMediaManager(self):
+        self.mediaManagerDock.setVisible(not self.mediaManagerDock.isVisible())
+
+    def toggleServiceManager(self):
+        self.serviceManagerDock.setVisible(not self.serviceManagerDock.isVisible())
+
+    def toggleThemeManager(self):
+        self.themeManagerDock.setVisible(not self.themeManagerDock.isVisible())
+
+    def setPreviewPanelVisibility(self, visible=None):
         """
         Sets the visibility of the preview panel including saving the setting
         and updating the menu.
@@ -950,12 +891,14 @@
                 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 +908,8 @@
                 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 +967,8 @@
             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'&%d %s' % (fileId + 1,
+                    QtCore.QFileInfo(filename).fileName()))
                 action.setData(QtCore.QVariant(filename))
                 self.connect(action, QtCore.SIGNAL(u'triggered()'),
                     self.ServiceManagerContents.onRecentServiceClicked)

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2011-03-31 07:31:08 +0000
+++ openlp/core/ui/servicemanager.py	2011-04-01 15:02:30 +0000
@@ -40,6 +40,7 @@
 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
 
 class ServiceManagerList(QtGui.QTreeWidget):
     """
@@ -164,38 +165,50 @@
             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')
+        ActionList.add_action(self.serviceManagerList.moveTop, u'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')
+        ActionList.add_action(self.serviceManagerList.moveUp, u'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')
+        ActionList.add_action(self.serviceManagerList.moveDown, u'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')
+        ActionList.add_action(self.serviceManagerList.moveBottom, u'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')
+        ActionList.add_action(self.serviceManagerList.down, u'Service')
         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')
+        ActionList.add_action(self.serviceManagerList.up, u'Service')
         self.serviceManagerList.up.setVisible(False)
         self.orderToolbar.addSeparator()
         self.serviceManagerList.delete = self.orderToolbar.addToolbarButton(
@@ -210,22 +223,26 @@
             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')
+        ActionList.add_action(self.serviceManagerList.expand, u'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')
+        ActionList.add_action(self.serviceManagerList.collapse, u'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')
+        ActionList.add_action(self.serviceManagerList.makeLive, u'Service')
         self.layout.addWidget(self.orderToolbar)
         # Connect up our signals and slots
         QtCore.QObject.connect(self.themeComboBox,
@@ -300,7 +317,6 @@
         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 +330,6 @@
             ])
         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

=== modified file 'openlp/core/ui/shortcutlistdialog.py'
--- openlp/core/ui/shortcutlistdialog.py	2011-03-24 19:04:02 +0000
+++ openlp/core/ui/shortcutlistdialog.py	2011-04-01 15:02:30 +0000
@@ -30,6 +30,7 @@
 
 class Ui_ShortcutListDialog(object):
     def setupUi(self, shortcutListDialog):
+        shortcutListDialog.resize(440, 450)
         shortcutListDialog.setObjectName(u'shortcutListDialog')
         self.dialogLayout = QtGui.QVBoxLayout(shortcutListDialog)
         self.dialogLayout.setObjectName(u'dialogLayout')
@@ -38,20 +39,14 @@
         self.treeWidget.setObjectName(u'treeWidget')
         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(
             build_icon(u':/system/system_configure_shortcuts.png'))
         self.shortcutButton.setCheckable(True)
         self.shortcutButton.setObjectName(u'shortcutButton')
+        self.shortcutButton.setFixedSize(150, 30)
         self.customLayout.addWidget(self.shortcutButton)
         self.clearShortcutButton = QtGui.QToolButton(shortcutListDialog)
         self.clearShortcutButton.setIcon(
@@ -80,9 +75,5 @@
             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'))

=== modified file 'openlp/core/ui/shortcutlistform.py'
--- openlp/core/ui/shortcutlistform.py	2011-03-24 19:04:02 +0000
+++ openlp/core/ui/shortcutlistform.py	2011-04-01 15:02:30 +0000
@@ -30,6 +30,7 @@
 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}')
@@ -40,21 +41,28 @@
     """
     The shortcut list dialog
     """
-
-    def __init__(self, parent):
-        """
-        Do some initialisation stuff
-        """
+#TODO: do not close on ESC
+#TODO: Fix Preview/Live controller (have the same shortcut)
+    def __init__(self, parent=None):
         QtGui.QDialog.__init__(self, parent)
         self.setupUi(self)
-        self.actionList = None
-        self.captureShortcut = False
+        self.column = -1
+        self.shortcutButton.setText(u'')
+        self.shortcutButton.setEnabled(False)
         QtCore.QObject.connect(self.shortcutButton,
             QtCore.SIGNAL(u'toggled(bool)'), self.onShortcutButtonClicked)
+        QtCore.QObject.connect(self.treeWidget,
+            QtCore.SIGNAL(u'itemPressed(QTreeWidgetItem*, int)'),
+            self.onItemPressed)
+        QtCore.QObject.connect(self.treeWidget,
+            QtCore.SIGNAL(u'itemDoubleClicked(QTreeWidgetItem*, int)'),
+            self.onItemDoubleClicked)
+        QtCore.QObject.connect(self.clearShortcutButton,
+            QtCore.SIGNAL(u'clicked(bool)'), self.onClearShortcutButtonClicked)
 
     def keyReleaseEvent(self, event):
         Qt = QtCore.Qt
-        if not self.captureShortcut:
+        if not self.shortcutButton.isChecked():
             return
         key = event.key()
         if key == Qt.Key_Shift or key == Qt.Key_Control or \
@@ -68,45 +76,167 @@
         if event.modifiers() & Qt.ShiftModifier == 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 item/action we are attempting to change.
+        changing_item = self.treeWidget.currentItem()
+        changing_action = changing_item.data(0, QtCore.Qt.UserRole).toPyObject()
+        shortcut_valid = True
+        for category in ActionList.categories:
+            for action in category.actions:
+                shortcuts = action.shortcuts()
+                if key_sequence not in shortcuts:
+                    continue
+                if action is changing_action:
+                    continue
+                # Have the same parentWidget, thus they cannot have the same
+                # shortcut.
+                #TODO: Does not fully work right now.
+                if action.parentWidget() is changing_action.parentWidget():
+                    shortcut_valid = False
+                if action.shortcutContext() == QtCore.Qt.WindowShortcut:
+                    shortcut_valid = False
+                if changing_action.shortcutContext() == QtCore.Qt.WindowShortcut:
+                    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)
+
+    def exec_(self):
+        self.reloadShortcutList()
         self.shortcutButton.setChecked(False)
-        self.captureShortcut = False
-
-    def exec_(self, actionList):
-        self.actionList = actionList
-        self.refreshActions()
+        self.shortcutButton.setEnabled(False)
+        self.shortcutButton.setText(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 ActionList.categories:
             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)
+        self.refreshShortcutList()
+
+    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 = item.data(0, QtCore.Qt.UserRole).toPyObject()
+            if action is None:
+                continue
+            if len(action.shortcuts()) == 0:
+                item.setText(1, u'')
+                item.setText(2, u'')
+            elif len(action.shortcuts()) == 1:
+                item.setText(1, action.shortcuts()[0].toString())
+                item.setText(2, u'')
+            else:
+                item.setText(1, action.shortcuts()[0].toString())
+                item.setText(2, action.shortcuts()[1].toString())
 
     def onShortcutButtonClicked(self, toggled):
-        self.captureShortcut = toggled
+        """
+        Save the new shortcut to the action if the button is unchanged.
+        """
+        if toggled:
+            return
+        item = self.treeWidget.currentItem()
+        if item is None:
+            return
+        action = item.data(0, QtCore.Qt.UserRole).toPyObject()
+        if action is None:
+            return
+        shortcuts = []
+        # We are changing the primary shortcut.
+        if self.column == 1:
+            shortcuts.append(QtGui.QKeySequence(self.shortcutButton.text()))
+            if len(action.shortcuts()) == 2:
+                shortcuts.append(action.shortcuts()[1])
+        # We are changing the secondary shortcut.
+        elif self.column == 2:
+            if len(action.shortcuts()) == 1:
+                shortcuts.append(action.shortcuts()[0])
+            shortcuts.append(QtGui.QKeySequence(self.shortcutButton.text()))
+        else:
+            return
+        action.setShortcuts(shortcuts)
+        self.refreshShortcutList()
+
+    def onItemDoubleClicked(self, item, column):
+        """
+        A item has been double clicked. ``The shortcutButton`` will be checked
+        and the item's shortcut will be displayed.
+        """
+        action = item.data(0, QtCore.Qt.UserRole).toPyObject()
+        if action is None:
+            return
+        self.shortcutButton.setChecked(True)
+        self.onItemPressed(item, column)
+
+    def onItemPressed(self, item, column):
+        """
+        A item has been pressed. We adjust the button's text to the action's
+        shortcut which is encapsulate in the item.
+        """
+        self.column = column
+        action = item.data(0, QtCore.Qt.UserRole).toPyObject()
+        self.shortcutButton.setEnabled(True)
+        text = u''
+        if action is None or column not in [1, 2]:
+            self.shortcutButton.setChecked(False)
+            self.shortcutButton.setEnabled(False)
+        elif column == 1 and len(action.shortcuts()) != 0:
+            text = action.shortcuts()[0].toString()
+        elif len(action.shortcuts()) == 2 and len(action.shortcuts()) != 0:
+            text = action.shortcuts()[1].toString()
+        self.shortcutButton.setText(text)
+
+    def onClearShortcutButtonClicked(self, toggled):
+        """
+        Restore the defaults of this 
+        """
+        item = self.treeWidget.currentItem()
+        self.shortcutButton.setChecked(False)
+        if item is None:
+            return
+        action = item.data(0, QtCore.Qt.UserRole).toPyObject()
+        if action is None:
+            return
+        action.setShortcuts(action.defaultShortcuts)
+        self.refreshShortcutList()
+        self.onItemPressed(item, self.column)
+
+    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 ActionList.categories:
+            for action in category.actions:
+                settings.setValue(
+                    action.objectName(), QtCore.QVariant(action.shortcuts()))
+        settings.endGroup()

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2011-03-26 19:50:15 +0000
+++ openlp/core/ui/slidecontroller.py	2011-04-01 15:02:30 +0000
@@ -34,6 +34,7 @@
     ItemCapabilities, translate
 from openlp.core.lib.ui import icon_action, UiStrings, shortcut_action
 from openlp.core.ui import HideMode, MainDisplay
+from openlp.core.utils.actions import ActionList
 
 log = logging.getLogger(__name__)
 
@@ -141,11 +142,13 @@
             u':/slides/slide_previous.png',
             translate('OpenLP.SlideController', 'Move to previous'),
             self.onSlideSelectedPrevious)
+        self.previousItem.setObjectName(u'previousItem')
         self.nextItem = self.toolbar.addToolbarButton(
             translate('OpenLP.SlideController', 'Next Slide'),
             u':/slides/slide_next.png',
             translate('OpenLP.SlideController', 'Move to next'),
             self.onSlideSelectedNext)
+        self.nextItem.setObjectName(u'nextItem')
         self.toolbar.addToolbarSeparator(u'Close Separator')
         if self.isLive:
             self.hideMenu = QtGui.QToolButton(self.toolbar)
@@ -154,16 +157,20 @@
             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, u'Live Toolbar')
             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, u'Live Toolbar')
             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,
+                u'Live Toolbar')
             self.desktopScreen.setText(
                 translate('OpenLP.SlideController', 'Show Desktop'))
             self.hideMenu.setDefaultAction(self.blankScreen)
@@ -291,12 +298,6 @@
         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 +363,34 @@
             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.setShortcuts([QtCore.Qt.Key_Up])
+        ActionList.add_action(self.previousItem, u'Preview Toolbar')
+        self.nextItem.setShortcuts([QtCore.Qt.Key_Down])
+        ActionList.add_action(self.nextItem, u'Preview Toolbar')
 
     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')
+        ActionList.add_action(self.previousItem, u'Live Toolbar')
         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')
+        ActionList.add_action(self.nextItem, u'Live Toolbar')
+        self.previousService = shortcut_action(parent, u'previousService',
+            [QtCore.Qt.Key_Left], self.servicePrevious, u'Live Toolbar')
+        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, u'Live Toolbar')
+        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, u'Live Toolbar')
+        self.escapeItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
+        self.escapeItem.setText(
+            translate('OpenLP.SlideController', 'Escape Item'))
 
     def liveEscape(self):
         self.display.setVisible(False)
@@ -741,10 +743,12 @@
         """
         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)
@@ -762,10 +766,12 @@
         self.blankPlugin(checked)
         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 +789,12 @@
         self.blankPlugin(checked)
         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)
@@ -1101,11 +1109,11 @@
         screen hide attributes
         """
         blank = None
-        if self.blankScreen.isChecked:
+        if self.blankScreen.isChecked():
             blank = self.blankScreen
-        if self.themeScreen.isChecked:
+        if self.themeScreen.isChecked():
             blank = self.themeScreen
-        if self.desktopScreen.isChecked:
+        if self.desktopScreen.isChecked():
             blank = self.desktopScreen
         if blank:
             blank.setChecked(False)

=== modified file 'openlp/core/utils/__init__.py'
--- openlp/core/utils/__init__.py	2011-03-25 16:29:39 +0000
+++ openlp/core/utils/__init__.py	2011-04-01 15:02:30 +0000
@@ -495,7 +495,7 @@
 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']

=== modified file 'openlp/core/utils/actions.py'
--- openlp/core/utils/actions.py	2011-03-24 19:04:02 +0000
+++ openlp/core/utils/actions.py	2011-04-01 15:02:30 +0000
@@ -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 @@
         Python 3 "next" method.
         """
         if self.index >= len(self.actions):
+            self.index = 0
             raise StopIteration
         else:
             self.index += 1
@@ -94,6 +97,12 @@
         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 @@
         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 @@
         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,31 @@
     has a weight by which it is sorted when iterating through the list of
     actions or categories.
     """
-    def __init__(self):
-        self.categories = CategoryList()
+    categories = CategoryList()
 
-    def add_action(self, action, category=u'Default', weight=None):
-        if category not in self.categories:
-            self.categories.append(category)
+    @staticmethod
+    def add_action(action, category, weight=None):
+        if category not in ActionList.categories:
+            ActionList.categories.append(category)
+        action.defaultShortcuts = action.shortcuts()
         if weight is None:
-            self.categories[category].actions.append(action)
+            ActionList.categories[category].actions.append(action)
         else:
-            self.categories[category].actions.add(action, weight)
+            ActionList.categories[category].actions.add(action, weight)
+        # 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()
+
+    @staticmethod
+    def remove_action(action, category):
+        if category not in ActionList.categories:
+            return
+        ActionList.categories[category].actions.remove(action)
+        # Remove empty categories.
+        if len(ActionList.categories[category].actions) == 0:
+            ActionList.categories.remove(category)

=== modified file 'openlp/plugins/alerts/alertsplugin.py'
--- openlp/plugins/alerts/alertsplugin.py	2011-03-24 19:04:02 +0000
+++ openlp/plugins/alerts/alertsplugin.py	2011-04-01 15:02:30 +0000
@@ -30,6 +30,8 @@
 
 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
+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 @@
             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,7 @@
         log.info(u'Alerts Initialising')
         Plugin.initialise(self)
         self.toolsAlertItem.setVisible(True)
+        ActionList.add_action(self.toolsAlertItem, u'Tools')
         self.liveController.alertTab = self.settings_tab
 
     def finalise(self):
@@ -84,6 +86,7 @@
         self.manager.finalise()
         Plugin.finalise(self)
         self.toolsAlertItem.setVisible(False)
+        ActionList.remove_action(self.toolsAlertItem, u'Tools')
 
     def toggleAlertsState(self):
         self.alertsActive = not self.alertsActive

=== modified file 'openlp/plugins/bibles/bibleplugin.py'
--- openlp/plugins/bibles/bibleplugin.py	2011-03-24 19:04:02 +0000
+++ openlp/plugins/bibles/bibleplugin.py	2011-04-01 15:02:30 +0000
@@ -29,6 +29,8 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.lib import Plugin, StringContent, build_icon, translate
+from openlp.core.lib.ui import base_action
+from openlp.core.utils.actions import ActionList
 from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem
 
 log = logging.getLogger(__name__)
@@ -50,6 +52,9 @@
             self.manager = BibleManager(self)
         Plugin.initialise(self)
         self.importBibleItem.setVisible(True)
+        ActionList.add_action(self.importBibleItem, u'Import')
+        # Do not add the action to the list yet.
+        #ActionList.add_action(self.exportBibleItem, u'Export')
         # Set to invisible until we can export bibles
         self.exportBibleItem.setVisible(False)
 
@@ -64,21 +69,18 @@
         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')
+        self.exportBibleItem = base_action(export_menu, u'exportBibleItem')
+        self.exportBibleItem.setText(translate('BiblesPlugin', '&Bible'))
         export_menu.addAction(self.exportBibleItem)
-        self.exportBibleItem.setText(translate('BiblesPlugin', '&Bible'))
         self.exportBibleItem.setVisible(False)
 
     def onBibleImportClick(self):

=== modified file 'openlp/plugins/songs/songsplugin.py'
--- openlp/plugins/songs/songsplugin.py	2011-03-30 18:52:58 +0000
+++ openlp/plugins/songs/songsplugin.py	2011-04-01 15:02:30 +0000
@@ -33,7 +33,8 @@
 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,9 @@
         log.info(u'Songs Initialising')
         Plugin.initialise(self)
         self.toolsReindexItem.setVisible(True)
+        ActionList.add_action(self.SongImportItem, u'Import')
+        ActionList.add_action(self.SongExportItem, u'Export')
+        ActionList.add_action(self.toolsReindexItem, u'Tools')
         self.mediaItem.displayResultsSong(
             self.manager.get_all_objects(Song, order_by_ref=Song.search_title))
 
@@ -78,10 +82,8 @@
             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 +101,8 @@
             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 +120,8 @@
             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 +258,7 @@
         log.info(u'Songs Finalising')
         self.manager.finalise()
         self.toolsReindexItem.setVisible(False)
+        ActionList.remove_action(self.SongImportItem, u'Import')
+        ActionList.remove_action(self.SongExportItem, u'Export')
+        ActionList.remove_action(self.toolsReindexItem, u'Tools')
         Plugin.finalise(self)

=== modified file 'openlp/plugins/songusage/songusageplugin.py'
--- openlp/plugins/songusage/songusageplugin.py	2011-03-24 19:04:02 +0000
+++ openlp/plugins/songusage/songusageplugin.py	2011-04-01 15:02:30 +0000
@@ -32,6 +32,8 @@
 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
+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 @@
         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 @@
         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,9 @@
             self.settingsSection + u'/active',
             QtCore.QVariant(False)).toBool()
         self.SongUsageStatus.setChecked(self.SongUsageActive)
+        ActionList.add_action(self.SongUsageDelete, u'Song Usage')
+        ActionList.add_action(self.SongUsageReport, u'Song Usage')
+        ActionList.add_action(self.SongUsageStatus, u'Song Usage')
         if self.manager is None:
             self.manager = Manager(u'songusage', init_schema)
         self.SongUsagedeleteform = SongUsageDeleteForm(self.manager,
@@ -131,6 +128,9 @@
         self.manager.finalise()
         Plugin.finalise(self)
         self.SongUsageMenu.menuAction().setVisible(False)
+        ActionList.remove_action(self.SongUsageDelete, u'Song Usage')
+        ActionList.remove_action(self.SongUsageReport, u'Song Usage')
+        ActionList.remove_action(self.SongUsageStatus, u'Song Usage')
         #stop any events being processed
         self.SongUsageActive = False
 


Follow ups