The buttons on the search bar dont behave like they do in the toolbars.
    Clicking on a button with a menu pops up the menu but does not perform
    the action. And right clicking on them has no effect. This will be
    confusing and a source of bug report noise. So maybe if the action has a
    menu, have it open on right click only, depending on popup_type in the
    action definition.

This problem arose because my code for keyboard shortcuts in Saved searches and Manage categories didn't work if the buttons on the search toolbar had menus. The popup menu appeared in some seemingly random spot. Of course it wasn't random, but ... I fixed it by changing the button to pop up the menu. That caused the behavior change.

I fixed this by removing the shortcuts from the main actions of Saved searches and Manage categories. Instead I used the API you provided in InterfaceAction to create menu items with shortcuts. With the change the 'main' qaction acts like it should, triggering the action for the button pressed. Right-click shows the menu as does clicking the down arrow.

Using a shortcut triggers the hidden menu action, which causes the code to search for any convenient place to put the menu. FWIW: this is a much better implementation. The 'hunt around' code only executes when the user presses a shortcut.

As a consequence existing shortcuts for Manage categories are lost because the shortcut name changed. Oh well. I doubt there are many, probably not any, calibre users who have defined a keyboard shortcut. They haven't had long -- only a release or two.
This commit is contained in:
Charles Haley 2022-10-19 21:32:46 +01:00
parent 288212f016
commit 83c00e877f
4 changed files with 44 additions and 18 deletions

View File

@ -2,6 +2,8 @@
# License: GPLv3 Copyright: 2022, Charles Haley
#
from qt.core import QToolButton
from calibre.gui2.actions import InterfaceAction
@ -11,6 +13,7 @@ class BooklistContextMenuAction(InterfaceAction):
action_spec = (_('Book list header menu'), 'context_menu.png',
_('Show the book list header context menu'), None)
action_type = 'current'
popup_type = QToolButton.ToolButtonPopupMode.InstantPopup
action_add_menu = False
dont_add_to = frozenset(['context-menu-device', 'menubar-device'])

View File

@ -2,6 +2,8 @@
# License: GPLv3 Copyright: 2022, Charles Haley
#
from qt.core import QMenu, QToolButton
from calibre.gui2.actions import InterfaceAction
@ -9,20 +11,30 @@ class ManageCategoriesAction(InterfaceAction):
name = 'Manage categories'
action_spec = (_('Manage categories'), 'tags.png',
_('Manage categories: authors, tags, series, etc.'), ())
_('Manage categories: authors, tags, series, etc.'), None)
action_type = 'current'
popup_type = QToolButton.ToolButtonPopupMode.InstantPopup
action_add_menu = True
dont_add_to = frozenset(['context-menu-device', 'menubar-device'])
def genesis(self):
self.menu = m = self.qaction.menu()
self.qaction.triggered.connect(self.show_menu)
m.aboutToShow.connect(self.about_to_show_menu)
# We want to show the menu when a toolbar button is clicked. Apparently
# the only way to do that is to scan the toolbar(s) for the action button
# then exec the associated menu. The search is done here to take adding and
# removing the action from toolbars into account.
# Create a "hidden" menu that can have a shortcut.
self.hidden_menu = QMenu()
self.shortcut_action = self.create_menu_action(
menu=self.hidden_menu,
unique_name=_('Manage categories'),
text=_('Manage categories: authors, tags, series, etc.'),
icon='tags.png',
triggered=self.show_menu)
# We want to show the menu when a shortcut is used. Apparently the only way
# to do that is to scan the toolbar(s) for the action button then exec the
# associated menu. The search is done here to take adding and removing the
# action from toolbars into account.
#
# If a shortcut is triggered and there isn't a toolbar button visible then
# show the menu in the upper left corner of the library view pane. Yes, this

View File

@ -2,7 +2,7 @@
# License: GPLv3 Copyright: 2022, Charles Haley
#
from qt.core import QPoint
from qt.core import QPoint, QMenu, QToolButton
from calibre.gui2.actions import InterfaceAction
@ -57,20 +57,29 @@ class SavedSearchesAction(InterfaceAction):
name = 'Saved searches'
action_spec = (_('Saved searches'), 'folder_saved_search.png',
_('Show a menu of saved searches'), ())
_('Show a menu of saved searches'), None)
action_type = 'current'
popup_type = QToolButton.ToolButtonPopupMode.InstantPopup
action_add_menu = True
dont_add_to = frozenset(('context-menu-device', 'menubar-device'))
def genesis(self):
self.menu = m = self.qaction.menu()
self.qaction.triggered.connect(self.show_menu)
m.aboutToShow.connect(self.about_to_show_menu)
# We want to show the menu when a toolbar button is clicked. Apparently
# the only way to do that is to scan the toolbar(s) for the action button
# then exec the associated menu. The search is done here to take adding and
# removing the action from toolbars into account.
# Create a "hidden" menu that can have a shortcut.
self.hidden_menu = QMenu()
self.shortcut_action = self.create_menu_action(
menu=self.hidden_menu,
unique_name=_('Saved searches'),
text=_('Show a menu of saved searches'),
icon='folder_saved_search.png',
triggered=self.show_menu)
# We want to show the menu when a shortcut is used. Apparently the only way
# to do that is to scan the toolbar(s) for the action button then exec the
# associated menu. The search is done here to take adding and removing the
# action from toolbars into account.
#
# If a shortcut is triggered and there isn't a toolbar button visible then
# show the menu in the upper left corner of the library view pane. Yes, this

View File

@ -15,7 +15,7 @@ from calibre.constants import ismacos
from calibre.gui2 import gprefs, native_menubar_defaults, config
from calibre.gui2.throbber import ThrobbingButton
from polyglot.builtins import itervalues
from calibre.gui2.widgets2 import RightClickButton
class RevealBar(QWidget): # {{{
@ -679,7 +679,7 @@ class BarsManager(QObject):
for ac in self.search_tool_bar_actions:
self.search_tool_bar.removeWidget(ac)
self.search_tool_bar.setContentsMargins(0, 0, 0, 0)
self.search_tool_bar.setContentsMargins(0, 0, 10, 0)
self.search_tool_bar.setSpacing(0)
self.search_tool_bar_actions = []
@ -693,8 +693,10 @@ class BarsManager(QObject):
self.search_tool_bar.addWidget(frame)
self.search_tool_bar_actions.append(frame)
elif what in self.parent().iactions:
qact = self.parent().iactions[what].qaction
tb = QToolButton()
act = self.parent().iactions[what]
qact = act.qaction
tb = RightClickButton()
tb.menu = qact.menu
tb.setContentsMargins(0, 0, 0, 0)
tb.setDefaultAction(qact)
if not gprefs['search_tool_bar_shows_text']:
@ -702,7 +704,7 @@ class BarsManager(QObject):
else:
tb.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
tb.setCursor(Qt.CursorShape.PointingHandCursor)
tb.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
tb.setPopupMode(act.popup_type)
tb.setAutoRaise(True)
self.search_tool_bar.addWidget(tb)
self.search_tool_bar_actions.append(tb)