mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-08-05 08:40:13 -04:00
Add a menu bar. By default the menu bar is hidden (except on OS X). You can add actions to it via Preferences->Toolbars.
This commit is contained in:
parent
8a7877fb73
commit
86e17cc100
@ -23,6 +23,10 @@ from calibre.utils.date import UNDEFINED_DATE
|
||||
# Setup gprefs {{{
|
||||
gprefs = JSONConfig('gui')
|
||||
|
||||
gprefs.defaults['action-layout-menubar'] = ()
|
||||
|
||||
gprefs.defaults['action-layout-menubar-device'] = ()
|
||||
|
||||
gprefs.defaults['action-layout-toolbar'] = (
|
||||
'Add Books', 'Edit Metadata', None, 'Convert Books', 'View', None,
|
||||
'Choose Library', 'Donate', None, 'Fetch News', 'Save To Disk',
|
||||
|
@ -75,7 +75,7 @@ class InterfaceAction(QObject):
|
||||
dont_remove_from = frozenset([])
|
||||
|
||||
all_locations = frozenset(['toolbar', 'toolbar-device', 'context-menu',
|
||||
'context-menu-device', 'toolbar-child'])
|
||||
'context-menu-device', 'toolbar-child', 'menubar', 'menubar-device'])
|
||||
|
||||
#: Type of action
|
||||
#: 'current' means acts on the current view
|
||||
|
@ -12,7 +12,7 @@ class AddToLibraryAction(InterfaceAction):
|
||||
name = 'Add To Library'
|
||||
action_spec = (_('Add books to library'), 'add_book.png',
|
||||
_('Add books to your calibre library from the connected device'), None)
|
||||
dont_add_to = frozenset(['toolbar', 'context-menu', 'toolbar-child'])
|
||||
dont_add_to = frozenset(['menubar', 'toolbar', 'context-menu', 'toolbar-child'])
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
|
@ -18,6 +18,7 @@ class FetchAnnotationsAction(InterfaceAction):
|
||||
|
||||
name = 'Fetch Annotations'
|
||||
action_spec = (_('Fetch annotations (experimental)'), None, None, None)
|
||||
dont_add_to = frozenset(['menubar', 'toolbar', 'context-menu', 'toolbar-child'])
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
|
@ -18,7 +18,7 @@ class GenerateCatalogAction(InterfaceAction):
|
||||
|
||||
name = 'Generate Catalog'
|
||||
action_spec = (_('Create a catalog of the books in your calibre library'), None, None, None)
|
||||
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
||||
|
||||
def generate_catalog(self):
|
||||
rows = self.gui.library_view.selectionModel().selectedRows()
|
||||
|
@ -80,7 +80,7 @@ class ChooseLibraryAction(InterfaceAction):
|
||||
name = 'Choose Library'
|
||||
action_spec = (_('%d books'), 'lt.png',
|
||||
_('Choose calibre library to work with'), None)
|
||||
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
||||
|
||||
def genesis(self):
|
||||
self.count_changed(0)
|
||||
@ -210,7 +210,6 @@ class ChooseLibraryAction(InterfaceAction):
|
||||
rename_actions, delete_actions, qs_actions,
|
||||
self.action_choose)
|
||||
|
||||
|
||||
def location_selected(self, loc):
|
||||
enabled = loc == 'library'
|
||||
self.qaction.setEnabled(enabled)
|
||||
|
@ -20,7 +20,7 @@ class ConvertAction(InterfaceAction):
|
||||
|
||||
name = 'Convert Books'
|
||||
action_spec = (_('Convert books'), 'convert.png', None, _('C'))
|
||||
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
|
@ -24,7 +24,7 @@ class ShareConnMenu(QMenu): # {{{
|
||||
|
||||
config_email = pyqtSignal()
|
||||
toggle_server = pyqtSignal()
|
||||
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QMenu.__init__(self, parent)
|
||||
@ -121,8 +121,7 @@ class SendToDeviceAction(InterfaceAction):
|
||||
|
||||
name = 'Send To Device'
|
||||
action_spec = (_('Send to device'), 'sync.png', None, _('D'))
|
||||
dont_remove_from = frozenset(['toolbar-device'])
|
||||
dont_add_to = frozenset(['toolbar', 'context-menu', 'toolbar-child'])
|
||||
dont_add_to = frozenset(['menubar', 'toolbar', 'context-menu', 'toolbar-child'])
|
||||
|
||||
def genesis(self):
|
||||
self.qaction.triggered.connect(self.do_sync)
|
||||
@ -169,7 +168,7 @@ class ConnectShareAction(InterfaceAction):
|
||||
|
||||
def toggle_content_server(self):
|
||||
if self.gui.content_server is None:
|
||||
self.gui.start_content_server()
|
||||
self.gui.start_content_server()
|
||||
else:
|
||||
self.gui.content_server.threaded_exit()
|
||||
self.stopping_msg = info_dialog(self.gui, _('Stopping'),
|
||||
|
@ -12,7 +12,7 @@ class EditCollectionsAction(InterfaceAction):
|
||||
name = 'Edit Collections'
|
||||
action_spec = (_('Manage collections'), None,
|
||||
_('Manage the collections on this device'), None)
|
||||
dont_add_to = frozenset(['toolbar', 'context-menu', 'toolbar-child'])
|
||||
dont_add_to = frozenset(['menubar', 'toolbar', 'context-menu', 'toolbar-child'])
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
|
@ -11,7 +11,7 @@ class NextMatchAction(InterfaceAction):
|
||||
name = 'Move to next highlighted book'
|
||||
action_spec = (_('Move to next match'), 'arrow-down.png',
|
||||
_('Move to next highlighted match'), [_('N'), _('F3')])
|
||||
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
|
@ -13,7 +13,7 @@ class OpenFolderAction(InterfaceAction):
|
||||
name = 'Open Folder'
|
||||
action_spec = (_('Open containing folder'), 'document_open.png', None,
|
||||
_('O'))
|
||||
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
|
@ -16,7 +16,6 @@ class PreferencesAction(InterfaceAction):
|
||||
|
||||
name = 'Preferences'
|
||||
action_spec = (_('Preferences'), 'config.png', None, _('Ctrl+P'))
|
||||
dont_remove_from = frozenset(['toolbar'])
|
||||
|
||||
def genesis(self):
|
||||
pm = QMenu()
|
||||
|
@ -15,7 +15,7 @@ class ShowBookDetailsAction(InterfaceAction):
|
||||
name = 'Show Book Details'
|
||||
action_spec = (_('Show book details'), 'dialog_information.png', None,
|
||||
_('I'))
|
||||
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
|
@ -15,7 +15,7 @@ class TweakEpubAction(InterfaceAction):
|
||||
action_spec = (_('Tweak ePub'), 'trim.png',
|
||||
_('Make small changes to ePub format books'),
|
||||
_('T'))
|
||||
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
|
@ -8,11 +8,11 @@ __docformat__ = 'restructuredtext en'
|
||||
from functools import partial
|
||||
|
||||
from PyQt4.Qt import (QIcon, Qt, QWidget, QToolBar, QSize,
|
||||
pyqtSignal, QToolButton, QMenu,
|
||||
pyqtSignal, QToolButton, QMenu, QMenuBar, QAction,
|
||||
QObject, QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QActionGroup)
|
||||
|
||||
|
||||
from calibre.constants import __appname__
|
||||
from calibre.constants import __appname__, isosx
|
||||
from calibre.gui2.search_box import SearchBox2, SavedSearchBox
|
||||
from calibre.gui2.throbber import ThrobbingButton
|
||||
from calibre.gui2 import gprefs
|
||||
@ -238,6 +238,80 @@ class Spacer(QWidget): # {{{
|
||||
self.l.addStretch(10)
|
||||
# }}}
|
||||
|
||||
class MenuAction(QAction):
|
||||
|
||||
def __init__(self, clone, parent):
|
||||
QAction.__init__(self, clone.text(), parent)
|
||||
self.clone = clone
|
||||
clone.changed.connect(self.clone_changed)
|
||||
|
||||
def clone_changed(self):
|
||||
self.setText(self.clone.text())
|
||||
|
||||
|
||||
class MenuBar(QMenuBar): # {{{
|
||||
|
||||
def __init__(self, location_manager, parent):
|
||||
QMenuBar.__init__(self, parent)
|
||||
self.gui = parent
|
||||
self.setNativeMenuBar(True)
|
||||
|
||||
self.location_manager = location_manager
|
||||
self.location_manager.locations_changed.connect(self.build_bar)
|
||||
self.added_actions = []
|
||||
|
||||
self.donate_action = QAction(_('Donate'), self)
|
||||
self.donate_menu = QMenu()
|
||||
self.donate_menu.addAction(self.gui.donate_action)
|
||||
self.donate_action.setMenu(self.donate_menu)
|
||||
self.build_bar()
|
||||
|
||||
def build_bar(self, changed_action=None):
|
||||
showing_device = self.location_manager.has_device
|
||||
actions = '-device' if showing_device else ''
|
||||
actions = gprefs['action-layout-menubar'+actions]
|
||||
|
||||
show_main = len(actions) > 0
|
||||
self.setVisible(show_main)
|
||||
|
||||
for ac in self.added_actions:
|
||||
m = ac.menu()
|
||||
if m is not None:
|
||||
m.setVisible(False)
|
||||
|
||||
self.clear()
|
||||
self.added_actions = []
|
||||
self.action_map = {}
|
||||
|
||||
for what in actions:
|
||||
if what is None:
|
||||
continue
|
||||
elif what == 'Location Manager':
|
||||
for ac in self.location_manager.available_actions:
|
||||
ac = self.build_menu(ac)
|
||||
self.addAction(ac)
|
||||
self.added_actions.append(ac)
|
||||
elif what == 'Donate':
|
||||
self.addAction(self.donate_action)
|
||||
elif what in self.gui.iactions:
|
||||
action = self.gui.iactions[what]
|
||||
ac = self.build_menu(action.qaction)
|
||||
self.addAction(ac)
|
||||
self.added_actions.append(ac)
|
||||
|
||||
def build_menu(self, action):
|
||||
m = action.menu()
|
||||
ac = MenuAction(action, self)
|
||||
if m is None:
|
||||
m = QMenu()
|
||||
m.addAction(action)
|
||||
ac.setMenu(m)
|
||||
return ac
|
||||
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
class ToolBar(QToolBar): # {{{
|
||||
|
||||
def __init__(self, donate, location_manager, child_bar, parent):
|
||||
@ -284,6 +358,8 @@ class ToolBar(QToolBar): # {{{
|
||||
mactions = gprefs['action-layout-toolbar'+mactions]
|
||||
cactions = gprefs['action-layout-toolbar-child']
|
||||
|
||||
show_main = len(mactions) > 0
|
||||
self.setVisible(show_main)
|
||||
show_child = len(cactions) > 0
|
||||
self.child_bar.setVisible(show_child)
|
||||
|
||||
@ -306,11 +382,16 @@ class ToolBar(QToolBar): # {{{
|
||||
bar.added_actions.append(ac)
|
||||
bar.setup_tool_button(bar, ac, QToolButton.MenuButtonPopup)
|
||||
elif what == 'Donate':
|
||||
self.d_widget = QWidget()
|
||||
self.d_widget.setLayout(QVBoxLayout())
|
||||
self.d_widget.layout().addWidget(self.donate_button)
|
||||
bar.addWidget(self.d_widget)
|
||||
self.showing_donate = True
|
||||
if isosx:
|
||||
bar.addAction(self.gui.donate_action)
|
||||
ch = self.setup_tool_button(bar, self.gui.donate_action)
|
||||
ch.setText(_('Donate'))
|
||||
else:
|
||||
self.d_widget = QWidget()
|
||||
self.d_widget.setLayout(QVBoxLayout())
|
||||
self.d_widget.layout().addWidget(self.donate_button)
|
||||
bar.addWidget(self.d_widget)
|
||||
self.showing_donate = True
|
||||
elif what in self.gui.iactions:
|
||||
action = self.gui.iactions[what]
|
||||
bar.addAction(action.qaction)
|
||||
@ -325,17 +406,20 @@ class ToolBar(QToolBar): # {{{
|
||||
ch.setAutoRaise(True)
|
||||
if ac.menu() is not None and menu_mode is not None:
|
||||
ch.setPopupMode(menu_mode)
|
||||
return ch
|
||||
|
||||
def resizeEvent(self, ev):
|
||||
QToolBar.resizeEvent(self, ev)
|
||||
style = Qt.ToolButtonTextUnderIcon
|
||||
p = gprefs['toolbar_text']
|
||||
if p == 'never':
|
||||
style = Qt.ToolButtonIconOnly
|
||||
s = gprefs['toolbar_icon_size']
|
||||
if s != 'off':
|
||||
p = gprefs['toolbar_text']
|
||||
if p == 'never':
|
||||
style = Qt.ToolButtonIconOnly
|
||||
|
||||
if p == 'auto' and self.preferred_width > self.width()+35 and \
|
||||
not gprefs['action-layout-toolbar-child']:
|
||||
style = Qt.ToolButtonIconOnly
|
||||
if p == 'auto' and self.preferred_width > self.width()+35 and \
|
||||
not gprefs['action-layout-toolbar-child']:
|
||||
style = Qt.ToolButtonIconOnly
|
||||
|
||||
self.setToolButtonStyle(style)
|
||||
|
||||
@ -421,6 +505,9 @@ class MainWindowMixin(object): # {{{
|
||||
self.location_manager, self.child_bar, self)
|
||||
self.addToolBar(Qt.TopToolBarArea, self.tool_bar)
|
||||
self.addToolBar(Qt.BottomToolBarArea, self.child_bar)
|
||||
self.menu_bar = MenuBar(self.location_manager, self)
|
||||
self.setMenuBar(self.menu_bar)
|
||||
self.setUnifiedTitleAndToolBarOnMac(True)
|
||||
|
||||
l = self.centralwidget.layout()
|
||||
l.addWidget(self.search_bar)
|
||||
|
@ -360,6 +360,7 @@ class Preferences(QMainWindow):
|
||||
self.gui.create_device_menu()
|
||||
self.gui.set_device_menu_items_state(bool(self.gui.device_connected))
|
||||
self.gui.tool_bar.build_bar()
|
||||
self.gui.menu_bar.build_bar()
|
||||
self.gui.build_context_menus()
|
||||
self.gui.tool_bar.apply_settings()
|
||||
|
||||
|
@ -34,9 +34,12 @@ class BaseModel(QAbstractListModel):
|
||||
if name == 'Location Manager':
|
||||
return FakeAction(name, None,
|
||||
_('Switch between library and device views'),
|
||||
dont_remove_from=set(['toolbar-device']))
|
||||
dont_add_to=frozenset(['menubar', 'toolbar',
|
||||
'toolbar-child', 'context-menu',
|
||||
'context-menu-device']))
|
||||
if name is None:
|
||||
return FakeAction('--- '+_('Separator')+' ---', None)
|
||||
return FakeAction('--- '+_('Separator')+' ---', None,
|
||||
dont_add_to=frozenset(['menubar', 'menubar-device']))
|
||||
try:
|
||||
return gui.iactions[name]
|
||||
except:
|
||||
@ -89,7 +92,7 @@ class AllModel(BaseModel):
|
||||
self._data = self.get_all_actions(current)
|
||||
|
||||
def get_all_actions(self, current):
|
||||
all = list(self.gui.iactions.keys()) + ['Donate']
|
||||
all = list(self.gui.iactions.keys()) + ['Donate', 'Location Manager']
|
||||
all = [x for x in all if x not in current] + [None]
|
||||
all = [self.name_to_action(x, self.gui) for x in all]
|
||||
all = [x for x in all if self.key not in x.dont_add_to]
|
||||
@ -208,12 +211,14 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
|
||||
LOCATIONS = [
|
||||
('toolbar', _('The main toolbar')),
|
||||
('toolbar-child', _('The optional second toolbar')),
|
||||
('toolbar-device', _('The main toolbar when a device is connected')),
|
||||
('toolbar-child', _('The optional second toolbar')),
|
||||
('menubar', _('The menubar')),
|
||||
('menubar-device', _('The menubar when a device is connected')),
|
||||
('context-menu', _('The context menu for the books in the '
|
||||
'calibre library')),
|
||||
('context-menu-device', _('The context menu for the books on '
|
||||
'the device'))
|
||||
'the device')),
|
||||
]
|
||||
|
||||
def genesis(self, gui):
|
||||
@ -284,6 +289,21 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
self.changed_signal.emit()
|
||||
|
||||
def commit(self):
|
||||
# Ensure preferences are showing in either the toolbar or
|
||||
# the menubar.
|
||||
pref_in_toolbar = lm_in_toolbar = False
|
||||
cm = self.models['toolbar']
|
||||
for x in cm[1]._data:
|
||||
if x.name == 'Preferences':
|
||||
pref_in_toolbar = True
|
||||
if x.name == 'Location Manager':
|
||||
lm_in_toolbar = True
|
||||
if not pref_in_toolbar:
|
||||
self.models['menubar'][1].add(['Preferences'])
|
||||
if not lm_in_toolbar:
|
||||
self.models['menubar-device'][1].add(['Location Manager'])
|
||||
|
||||
# Save data.
|
||||
for am, cm in self.models.values():
|
||||
cm.commit()
|
||||
return False
|
||||
|
@ -153,6 +153,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
|
||||
for ac in self.iactions.values():
|
||||
ac.do_genesis()
|
||||
self.donate_action = QAction(QIcon(I('donate.png')), _('&Donate to support calibre'), self)
|
||||
MainWindowMixin.__init__(self, db)
|
||||
|
||||
# Jobs Button {{{
|
||||
@ -186,8 +187,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
self.system_tray_menu = QMenu(self)
|
||||
self.restore_action = self.system_tray_menu.addAction(
|
||||
QIcon(I('page.png')), _('&Restore'))
|
||||
self.donate_action = self.system_tray_menu.addAction(
|
||||
QIcon(I('donate.png')), _('&Donate to support calibre'))
|
||||
self.system_tray_menu.addAction(self.donate_action)
|
||||
self.donate_button.setDefaultAction(self.donate_action)
|
||||
self.donate_button.setStatusTip(self.donate_button.toolTip())
|
||||
self.eject_action = self.system_tray_menu.addAction(
|
||||
|
Loading…
x
Reference in New Issue
Block a user