Cleanup creation of menus for toolbar buttons and add the keyboard shortcut G for Get Books

This commit is contained in:
Kovid Goyal 2011-08-02 14:46:46 -06:00
parent a5e8b23bfe
commit f929fe73df
13 changed files with 80 additions and 61 deletions

View File

@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
from functools import partial
from zipfile import ZipFile
from PyQt4.Qt import QToolButton, QAction, QIcon, QObject
from PyQt4.Qt import QToolButton, QAction, QIcon, QObject, QMenu
from calibre.gui2 import Dispatcher
@ -66,6 +66,14 @@ class InterfaceAction(QObject):
#: shortcut must be a translated string if not None
action_spec = ('text', 'icon', None, None)
#: If True, a menu is automatically created and added to self.qaction
action_add_menu = False
#: If True, a clone of self.qaction is added to the menu of self.qaction
#: If you want the text of this action to be different from that of
#: self.qaction, set this variable to the new text
action_menu_clone_qaction = False
#: Set of locations to which this action must not be added.
#: See :attr:`all_locations` for a list of possible locations
dont_add_to = frozenset([])
@ -94,6 +102,7 @@ class InterfaceAction(QObject):
self.Dispatcher = partial(Dispatcher, parent=self)
self.create_action()
self.gui.addAction(self.qaction)
self.gui.addAction(self.menuless_qaction)
self.genesis()
def create_action(self, spec=None, attr='qaction'):
@ -104,18 +113,29 @@ class InterfaceAction(QObject):
action = QAction(QIcon(I(icon)), text, self.gui)
else:
action = QAction(text, self.gui)
action.setAutoRepeat(self.auto_repeat)
text = tooltip if tooltip else text
action.setToolTip(text)
action.setStatusTip(text)
action.setWhatsThis(text)
action.setAutoRepeat(False)
if attr == 'qaction':
mt = (action.text() if self.action_menu_clone_qaction is True else
unicode(self.action_menu_clone_qaction))
self.menuless_qaction = ma = QAction(action.icon(), mt, self.gui)
ma.triggered.connect(action.trigger)
for a in ((action, ma) if attr == 'qaction' else (action,)):
a.setAutoRepeat(self.auto_repeat)
text = tooltip if tooltip else text
a.setToolTip(text)
a.setStatusTip(text)
a.setWhatsThis(text)
if shortcut:
a = ma if attr == 'qaction' else action
if isinstance(shortcut, list):
action.setShortcuts(shortcut)
a.setShortcuts(shortcut)
else:
action.setShortcut(shortcut)
a.setShortcut(shortcut)
setattr(self, attr, action)
if attr == 'qaction' and self.action_add_menu:
menu = QMenu()
action.setMenu(menu)
if self.action_menu_clone_qaction:
menu.addAction(self.menuless_qaction)
return action
def load_resources(self, names):

View File

@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
import os
from functools import partial
from PyQt4.Qt import QPixmap, QMenu, QTimer
from PyQt4.Qt import QPixmap, QTimer
from calibre.gui2 import error_dialog, choose_files, \
@ -48,12 +48,12 @@ class AddAction(InterfaceAction):
_('Add books to the calibre library/device from files on your computer')
, _('A'))
action_type = 'current'
action_add_menu = True
action_menu_clone_qaction = _('Add books from a single directory')
def genesis(self):
self._add_filesystem_book = self.Dispatcher(self.__add_filesystem_book)
self.add_menu = QMenu()
self.add_menu.addAction(_('Add books from a single directory'),
self.add_books)
self.add_menu = self.qaction.menu()
self.add_menu.addAction(_('Add books from directories, including '
'sub-directories (One book per directory, assumes every ebook '
'file is the same book in a different format)'),
@ -69,7 +69,6 @@ class AddAction(InterfaceAction):
self.add_menu.addAction(_('Add files to selected book records'),
self.add_formats, _('Shift+A'))
self.qaction.setMenu(self.add_menu)
self.qaction.triggered.connect(self.add_books)
def location_selected(self, loc):

View File

@ -82,23 +82,20 @@ class ChooseLibraryAction(InterfaceAction):
action_spec = (_('%d books'), 'lt.png',
_('Choose calibre library to work with'), None)
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
action_add_menu = True
action_menu_clone_qaction = _('Switch/create library...')
def genesis(self):
self.count_changed(0)
self.qaction.triggered.connect(self.choose_library,
type=Qt.QueuedConnection)
self.action_choose = self.menuless_qaction
self.stats = LibraryUsageStats()
self.popup_type = (QToolButton.InstantPopup if len(self.stats.stats) > 1 else
QToolButton.MenuButtonPopup)
self.create_action(spec=(_('Switch/create library...'), 'lt.png', None,
None), attr='action_choose')
self.action_choose.triggered.connect(self.choose_library,
type=Qt.QueuedConnection)
self.choose_menu = QMenu(self.gui)
self.qaction.setMenu(self.choose_menu)
self.choose_menu = self.qaction.menu()
if not os.environ.get('CALIBRE_OVERRIDE_DATABASE_PATH', None):
self.choose_menu.addAction(self.action_choose)
@ -110,7 +107,7 @@ class ChooseLibraryAction(InterfaceAction):
self.delete_menu = QMenu(_('Remove library'))
self.delete_menu_action = self.choose_menu.addMenu(self.delete_menu)
ac = self.create_action(spec=(_('Pick a random book'), 'catalog.png',
ac = self.create_action(spec=(_('Pick a random book'), 'random.png',
None, None), attr='action_pick_random')
ac.triggered.connect(self.pick_random)
self.choose_menu.addAction(ac)

View File

@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
import os
from functools import partial
from PyQt4.Qt import QModelIndex, QMenu
from PyQt4.Qt import QModelIndex, QIcon
from calibre.gui2 import error_dialog, Dispatcher
from calibre.gui2.tools import convert_single_ebook, convert_bulk_ebook
@ -22,18 +22,18 @@ class ConvertAction(InterfaceAction):
action_spec = (_('Convert books'), 'convert.png', None, _('C'))
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
action_type = 'current'
action_add_menu = True
def genesis(self):
cm = QMenu()
cm.addAction(_('Convert individually'), partial(self.convert_ebook,
cm = self.qaction.menu()
cm.addAction(self.qaction.icon(), _('Convert individually'), partial(self.convert_ebook,
False, bulk=False))
cm.addAction(_('Bulk convert'),
partial(self.convert_ebook, False, bulk=True))
cm.addSeparator()
ac = cm.addAction(
ac = cm.addAction(QIcon(I('catalog.png')),
_('Create a catalog of the books in your calibre library'))
ac.triggered.connect(self.gui.iactions['Generate Catalog'].generate_catalog)
self.qaction.setMenu(cm)
self.qaction.triggered.connect(self.convert_ebook)
self.convert_menu = cm
self.conversion_jobs = {}

View File

@ -9,7 +9,7 @@ import os
from functools import partial
from threading import Thread
from PyQt4.Qt import QMenu, QToolButton
from PyQt4.Qt import QToolButton
from calibre.gui2.actions import InterfaceAction
from calibre.gui2 import error_dialog, Dispatcher, warning_dialog
@ -95,10 +95,10 @@ class CopyToLibraryAction(InterfaceAction):
popup_type = QToolButton.InstantPopup
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
action_type = 'current'
action_add_menu = True
def genesis(self):
self.menu = QMenu(self.gui)
self.qaction.setMenu(self.menu)
self.menu = self.qaction.menu()
@property
def stats(self):

View File

@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
from functools import partial
from PyQt4.Qt import QMenu, QObject, QTimer
from PyQt4.Qt import QObject, QTimer
from calibre.gui2 import error_dialog, question_dialog
from calibre.gui2.dialogs.delete_matching_from_device import DeleteMatchingFromDeviceDialog
@ -18,7 +18,7 @@ from calibre.utils.recycle_bin import can_recycle
single_shot = partial(QTimer.singleShot, 10)
class MultiDeleter(QObject):
class MultiDeleter(QObject): # {{{
def __init__(self, gui, ids, callback):
from calibre.gui2.dialogs.progress import ProgressDialog
@ -77,17 +77,19 @@ class MultiDeleter(QObject):
error_dialog(self.gui, _('Failed to delete'),
_('Failed to delete some books, click the Show Details button'
' for details.'), det_msg='\n\n'.join(msg), show=True)
# }}}
class DeleteAction(InterfaceAction):
name = 'Remove Books'
action_spec = (_('Remove books'), 'trash.png', None, 'Del')
action_type = 'current'
action_add_menu = True
action_menu_clone_qaction = _('Remove selected books')
def genesis(self):
self.qaction.triggered.connect(self.delete_books)
self.delete_menu = QMenu()
self.delete_menu.addAction(_('Remove selected books'), self.delete_books)
self.delete_menu = self.qaction.menu()
self.delete_menu.addAction(
_('Remove files of a specific format from selected books..'),
self.delete_selected_formats)

View File

@ -24,12 +24,13 @@ class EditMetadataAction(InterfaceAction):
name = 'Edit Metadata'
action_spec = (_('Edit metadata'), 'edit_input.png', None, _('E'))
action_type = 'current'
action_add_menu = True
def genesis(self):
self.create_action(spec=(_('Merge book records'), 'merge_books.png',
None, _('M')), attr='action_merge')
md = QMenu()
md.addAction(_('Edit metadata individually'),
md = self.qaction.menu()
md.addAction(self.qaction.icon(), _('Edit metadata individually'),
partial(self.edit_metadata, False, bulk=False))
md.addSeparator()
md.addAction(_('Edit metadata in bulk'),
@ -56,7 +57,6 @@ class EditMetadataAction(InterfaceAction):
md.addAction(self.action_merge)
self.qaction.triggered.connect(self.edit_metadata)
self.qaction.setMenu(md)
self.action_merge.triggered.connect(self.merge_books)
def location_selected(self, loc):

View File

@ -5,7 +5,7 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import QIcon, QMenu, Qt
from PyQt4.Qt import QIcon, Qt
from calibre.gui2.actions import InterfaceAction
from calibre.gui2.preferences.main import Preferences
@ -16,12 +16,13 @@ class PreferencesAction(InterfaceAction):
name = 'Preferences'
action_spec = (_('Preferences'), 'config.png', None, _('Ctrl+P'))
action_add_menu = True
action_menu_clone_qaction = _('Change calibre behavior')
def genesis(self):
pm = QMenu()
pm.addAction(QIcon(I('config.png')), _('Preferences'), self.do_config)
pm = self.qaction.menu()
if isosx:
pm.addAction(QIcon(I('config.png')), _('Change calibre behavior'), self.do_config)
pm.addAction(QIcon(I('config.png')), _('Preferences'), self.do_config)
pm.addAction(QIcon(I('wizard.png')), _('Run welcome wizard'),
self.gui.run_wizard)
pm.addAction(QIcon(I('plugins/plugin_updater.png')),
@ -33,7 +34,6 @@ class PreferencesAction(InterfaceAction):
ac.setShortcut('Ctrl+Shift+R')
self.gui.addAction(ac)
self.qaction.setMenu(pm)
self.preferences_menu = pm
for x in (self.gui.preferences_action, self.qaction):
x.triggered.connect(self.do_config)

View File

@ -38,12 +38,12 @@ class SaveToDiskAction(InterfaceAction):
name = "Save To Disk"
action_spec = (_('Save to disk'), 'save.png', None, _('S'))
action_type = 'current'
action_add_menu = True
action_menu_clone_qaction = True
def genesis(self):
self.qaction.triggered.connect(self.save_to_disk)
self.save_menu = QMenu()
self.save_menu.addAction(_('Save to disk'), partial(self.save_to_disk,
False))
self.save_menu = self.qaction.menu()
self.save_menu.addAction(_('Save to disk in a single directory'),
partial(self.save_to_single_dir, False))
self.save_menu.addAction(_('Save only %s format to disk')%
@ -56,7 +56,6 @@ class SaveToDiskAction(InterfaceAction):
self.save_sub_menu = SaveMenu(self.gui)
self.save_sub_menu_action = self.save_menu.addMenu(self.save_sub_menu)
self.save_sub_menu.save_fmt.connect(self.save_specific_format_disk)
self.qaction.setMenu(self.save_menu)
def location_selected(self, loc):
enabled = loc == 'library'

View File

@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
from functools import partial
from PyQt4.Qt import QMenu, QToolButton
from PyQt4.Qt import QToolButton
from calibre.gui2.actions import InterfaceAction
@ -17,9 +17,10 @@ class SimilarBooksAction(InterfaceAction):
action_spec = (_('Similar books...'), None, None, None)
popup_type = QToolButton.InstantPopup
action_type = 'current'
action_add_menu = True
def genesis(self):
m = QMenu(self.gui)
m = self.qaction.menu()
for text, icon, target, shortcut in [
(_('Books by same author'), 'user_profile.png', 'authors', _('Alt+A')),
(_('Books in this series'), 'books_in_series.png', 'series',
@ -31,7 +32,6 @@ class SimilarBooksAction(InterfaceAction):
m.addAction(ac)
ac.triggered.connect(partial(self.show_similar_books, target))
self.qaction.setMenu(m)
self.similar_menu = m
def show_similar_books(self, type, *args):
search, join = [], ' '

View File

@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
from functools import partial
from PyQt4.Qt import QMenu, QIcon, QSize
from PyQt4.Qt import QIcon, QSize
from calibre.gui2 import error_dialog
from calibre.gui2.actions import InterfaceAction
@ -17,16 +17,18 @@ from calibre.gui2.dialogs.confirm_delete import confirm
class StoreAction(InterfaceAction):
name = 'Store'
action_spec = (_('Get books'), 'store.png', None, None)
action_spec = (_('Get books'), 'store.png', None, _('G'))
action_add_menu = True
action_menu_clone_qaction = _('Search for ebooks')
def genesis(self):
self.qaction.triggered.connect(self.do_search)
self.store_menu = QMenu()
self.store_menu = self.qaction.menu()
self.load_menu()
def load_menu(self):
self.store_menu.clear()
self.store_menu.addAction(_('Search for ebooks'), self.search)
self.store_menu.addAction(self.menuless_qaction)
self.store_menu.addAction(_('Search for this author'), self.search_author)
self.store_menu.addAction(_('Search for this title'), self.search_title)
self.store_menu.addAction(_('Search for this book'), self.search_author_title)
@ -41,7 +43,6 @@ class StoreAction(InterfaceAction):
self.store_list_menu.addAction(n, partial(self.open_store, p))
self.store_menu.addSeparator()
self.store_menu.addAction(_('Choose stores'), self.choose)
self.qaction.setMenu(self.store_menu)
def do_search(self):
return self.search()

View File

@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
import os, time
from PyQt4.Qt import Qt, QMenu, QAction, pyqtSignal
from PyQt4.Qt import Qt, QAction, pyqtSignal
from calibre.constants import isosx
from calibre.gui2 import error_dialog, Dispatcher, question_dialog, config, \
@ -35,20 +35,19 @@ class ViewAction(InterfaceAction):
name = 'View'
action_spec = (_('View'), 'view.png', None, _('V'))
action_type = 'current'
action_add_menu = True
action_menu_clone_qaction = True
def genesis(self):
self.persistent_files = []
self.qaction.triggered.connect(self.view_book)
self.view_menu = QMenu()
self.view_action = self.menuless_qaction
self.view_menu = self.qaction.menu()
ac = self.view_specific_action = QAction(_('View specific format'),
self.gui)
self.qaction.setMenu(self.view_menu)
ac.setShortcut(Qt.AltModifier+Qt.Key_V)
ac.triggered.connect(self.view_specific_format, type=Qt.QueuedConnection)
ac = self.view_action = QAction(self.qaction.icon(),
self.qaction.text(), self.gui)
ac.triggered.connect(self.view_book)
ac = self.create_action(spec=(_('Read a random book'), 'catalog.png',
ac = self.create_action(spec=(_('Read a random book'), 'random.png',
None, None), attr='action_pick_random')
ac.triggered.connect(self.view_random)
ac = self.clear_history_action = QAction(

View File

@ -527,6 +527,8 @@ Calibre has several keyboard shortcuts to save you time and mouse movement. Thes
- Remove selected Books
* - :kbd:`E`
- Edit metadata of selected books
* - :kbd:`G`
- Get Books
* - :kbd:`I`
- Show book details
* - :kbd:`M`