diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 9ff3d3a95f..c8793f9df6 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -415,6 +415,8 @@ def create_defs(): defs['tag_browser_allow_keyboard_focus'] = False defs['book_list_tooltips'] = True defs['show_layout_buttons'] = False + # defs['show_sb_preference_button'] = False + defs['show_sb_all_actions_button'] = False defs['bd_show_cover'] = True defs['bd_overlay_cover_size'] = False defs['tags_browser_category_icons'] = {} diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index 3c24995491..5282d6b911 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -68,6 +68,13 @@ def show_menu_under_widget(gui, menu, action, name): return except Exception: continue + # Is it one of the status bar buttons? + for button in gui.status_bar_extra_buttons: + if name == button.action_name and button.isVisible(): + r = button.geometry() + p = gui.status_bar + menu.exec(p.mapToGlobal(QPoint(r.x()+2, r.height()-2))) + return # No visible button found. Fall back to displaying in upper left corner # of the library view. menu.exec(gui.library_view.mapToGlobal(QPoint(10, 10))) diff --git a/src/calibre/gui2/actions/all_actions.py b/src/calibre/gui2/actions/all_actions.py index 2ef657f8cd..aaf2c9463a 100644 --- a/src/calibre/gui2/actions/all_actions.py +++ b/src/calibre/gui2/actions/all_actions.py @@ -14,7 +14,7 @@ from calibre.utils.icu import sort_key class AllGUIActions(InterfaceAction): name = 'All GUI actions' - action_spec = (_('All GUI actions'), 'wizard.png', + action_spec = (_('GUI actions'), 'wizard.png', _("Show a menu of all available GUI and plugin actions.\nThis menu " "is not available when looking at books on a device"), None) @@ -33,10 +33,9 @@ class AllGUIActions(InterfaceAction): self.shortcut_action = self.create_menu_action( menu=self.hidden_menu, unique_name='Main window layout', - shortcut=None, - text=_("Save and restore layout item sizes, and add/remove/toggle " - "layout items such as the search bar, tag browser, etc. "), - icon='layout.png', + shortcut='Ctrl+F1', + text=_("Show a menu of all available GUI and plugin actions."), + icon='wizard.png', triggered=self.show_menu) # We want to show the menu when a shortcut is used. Apparently the only way @@ -59,9 +58,6 @@ class AllGUIActions(InterfaceAction): def about_to_show_menu(self): self.populate_menu() - def location_selected(self, loc): - self.qaction.setEnabled(loc == 'library') - def populate_menu(self): # Need to do this on every invocation because shortcuts can change m = self.qaction.menu() @@ -127,20 +123,23 @@ class AllGUIActions(InterfaceAction): if act.popup_type == QToolButton.ToolButtonPopupMode.MenuButtonPopup: if getattr(act, 'action_add_menu', None) or (getattr(act, 'qaction', None) and act.qaction.menu() and act.qaction.menu().children()): # The action offers both a 'click' and a menu. Use the menu. - menu.addAction(icon, menu_text, partial(self._do_menu, display_name, act)) + ma = menu.addAction(icon, menu_text, partial(self._do_menu, display_name, act)) else: # The action is a dialog. - menu.addAction(act.qaction.icon(), menu_text, partial(self._do_action, act)) + ma = menu.addAction(act.qaction.icon(), menu_text, partial(self._do_action, act)) else: # The action is a menu. - menu.addAction(icon, menu_text, partial(self._do_menu, display_name, act)) + ma = menu.addAction(icon, menu_text, partial(self._do_menu, display_name, act)) + # Disable the menu line if the underlying qaction is disabled. This + # happens when devices are connected and in some other contexts. + ma.setEnabled(act.qaction.isEnabled()) # Finally the real work, building the action menu. Partition long lists - # of actions into sublists of some arbitrary length. + # of actions into mostly-equal-length sublists of some arbitrary length. def partition(names): - count_in_partition = 10 # arbitrary - if len(names) >= count_in_partition: - partition_count = len(names) // (count_in_partition - 1) + max_in_partition = 10 # arbitrary + if len(names) >= max_in_partition: + partition_count = ceil(len(names) / max_in_partition) step = int(ceil(len(names) / partition_count)) for first in range(0, len(names), step): last = min(first + step - 1, len(names) - 1) @@ -166,6 +165,7 @@ class AllGUIActions(InterfaceAction): partition(builtin_actions) # Add access to the toolbars and keyboard shortcuts preferences dialogs m.addSection(_('Preferences') + ' ') + m.addAction(QIcon.ic('wizard.png'), _('Main dialog'), self.gui.iactions['Preferences'].qaction.trigger) m.addAction(QIcon.ic('wizard.png'), _('Toolbars'), self._do_pref_toolbar) m.addAction(QIcon.ic('keyboard-prefs.png'), _('Keyboard shortcuts'), self._do_pref_shortcuts) diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index 7d824cb909..cb2d1eb233 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -487,6 +487,29 @@ class VLTabs(QTabBar): # {{{ # }}} +class StatusBarButton(QToolButton): + + def __init__(self, parent, action_name, pref_name, on_click): + super().__init__(parent=parent) + act = parent.iactions[action_name] + self.action_name = action_name + self.setCursor(Qt.CursorShape.PointingHandCursor) + self.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup) + self.setAutoRaise(True) + self.setIcon(QIcon.ic(act.action_spec[1])) + self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon) + self.setText(act.action_spec[0]) + self.setToolTip(act.action_spec[2]) + self.setVisible(gprefs[pref_name]) + parent.status_bar.addPermanentWidget(self) + if on_click == 'menu': + self.setMenu(act.qaction.menu()) + elif on_click == 'trigger': + self.clicked.connect(act.qaction.trigger) + else: + raise ValueError(f'make_status_line_action_button: invalid on_click ({on_click}') + + class LayoutMixin: # {{{ def __init__(self, *args, **kwargs): @@ -573,6 +596,15 @@ class LayoutMixin: # {{{ b.setToolTip(_( 'Show and hide various parts of the calibre main window')) self.status_bar.addPermanentWidget(b) + + # These must be after the layout button because it can be expanded into + # the component buttons. Order: last is right-most. + # The preferences status bar button isn't (yet) allowed on the status bar + # self.sb_preferences_button = StatusBarButton(self, 'Preferences', 'show_sb_preference_button', 'trigger') + self.sb_all_gui_actions_button = StatusBarButton(self, 'All GUI actions', + 'show_sb_all_actions_button', 'menu') + self.status_bar_extra_buttons = (self.sb_all_gui_actions_button,) + self.status_bar.addPermanentWidget(self.jobs_button) self.setStatusBar(self.status_bar) self.status_bar.update_label.linkActivated.connect(self.update_link_clicked) diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index aa2bac5254..6568558df3 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -632,6 +632,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): r('dnd_merge', gprefs) r('wrap_toolbar_text', gprefs, restart_required=True) r('show_layout_buttons', gprefs) + r('show_sb_all_actions_button', gprefs) + # r('show_sb_preference_button', gprefs) r('row_numbers_in_book_list', gprefs) r('tag_browser_old_look', gprefs) r('tag_browser_hide_empty_categories', gprefs) @@ -1277,6 +1279,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): qv = get_quickview_action_plugin() if qv: qv.refill_quickview() + gui.sb_all_gui_actions_button.setVisible(gprefs['show_sb_all_actions_button']) + # gui.sb_preferences_button.setVisible(gprefs['show_sb_preference_button']) if __name__ == '__main__': diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index e105ce3d30..c2bc905458 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -41,6 +41,23 @@ + + + + + + Qt::Horizontal + + + + 20 + 1 + + + + + + @@ -190,13 +207,6 @@ - - - - Show &layout buttons in the status bar - - - @@ -267,6 +277,42 @@ + + + + Status bar buttons + + + + + + Show &layout buttons + + + + + + + S&how GUI actions button + + + + + + + Qt::Vertical + + + + 10 + 20 + + + + + + +