Bug 1993622: Toolbar button oddities on search bar

The major change is using a new class SearchToolBar to mimic a ToolBar. This lets the BarsManager treat the SearchToolBar as a "normal" toolbar. This fixed the two problems reported in this bug report.

In addition I fixed:
- "Mark Books" to install its event listener on SearchToolBar buttons.
- SavedSearchs to find SearchToolBar buttons when using keyboard shortcuts.
- Prevent the location manager and the donate action from being added to the SearchToolBar.
This commit is contained in:
Charles Haley 2022-10-20 16:13:06 +01:00
parent fd8270d72c
commit f2a5c18a4f
5 changed files with 98 additions and 45 deletions

View File

@ -97,7 +97,7 @@ class InterfaceAction(QObject):
all_locations = frozenset(['toolbar', 'toolbar-device', 'context-menu', all_locations = frozenset(['toolbar', 'toolbar-device', 'context-menu',
'context-menu-device', 'toolbar-child', 'menubar', 'menubar-device', 'context-menu-device', 'toolbar-child', 'menubar', 'menubar-device',
'context-menu-cover-browser', 'context-menu-split']) 'context-menu-cover-browser', 'context-menu-split', 'searchbar'])
#: Type of action #: Type of action
#: 'current' means acts on the current view #: 'current' means acts on the current view

View File

@ -146,7 +146,7 @@ class MarkBooksAction(InterfaceAction):
connect_lambda(a.triggered, self, lambda self: self.mark_field('series', False)) connect_lambda(a.triggered, self, lambda self: self.mark_field('series', False))
def gui_layout_complete(self): def gui_layout_complete(self):
for x in self.gui.bars_manager.main_bars + self.gui.bars_manager.child_bars: for x in self.gui.bars_manager.bars:
try: try:
w = x.widgetForAction(self.qaction) w = x.widgetForAction(self.qaction)
w.installEventFilter(self) w.installEventFilter(self)

View File

@ -9,7 +9,7 @@ from calibre.gui2.actions import InterfaceAction
def show_menu_under_widget(gui, menu, action, name): def show_menu_under_widget(gui, menu, action, name):
# First try the tool bar # First try the tool bar
for x in gui.bars_manager.main_bars + gui.bars_manager.child_bars: for x in gui.bars_manager.bars:
try: try:
w = x.widgetForAction(action) w = x.widgetForAction(action)
# It seems that multiple copies of the action can exist, such as # It seems that multiple copies of the action can exist, such as

View File

@ -620,9 +620,98 @@ class AdaptMenuBarForDialog:
self.menu_bar.adapt_for_dialog(False) self.menu_bar.adapt_for_dialog(False)
class SearchToolBar(QHBoxLayout):
# Simulate an instance of the above Toolbar class using widgets instead of
# actions. The tool buttons are fixed size and the text is either gone or to
# the right.
def __init__(self, gui):
QHBoxLayout.__init__(self)
self.search_tool_bar_widgets = []
self.gui = gui
self.donate_button = None
def init_bar(self, actions):
for widget in self.search_tool_bar_widgets:
self.removeWidget(widget)
self.setContentsMargins(0, 0, 10, 0)
self.setSpacing(0)
self.search_tool_bar_widgets = []
self.search_tool_bar_actions = []
for what in gprefs['action-layout-searchbar']:
if what is None:
frame = QFrame()
frame.setFrameShape(QFrame.Shape.VLine)
frame.setFrameShadow(QFrame.Shadow.Sunken)
frame.setLineWidth(1)
frame.setContentsMargins(0, 5, 0, 5)
self.addWidget(frame)
self.search_tool_bar_widgets.append(frame)
self.search_tool_bar_actions.append(None)
elif what in self.gui.iactions:
act = self.gui.iactions[what]
qact = act.qaction
tb = RightClickButton() # Do we really need to support right-click?
tb.menu = qact.menu
tb.setContentsMargins(0, 0, 0, 0)
tb.setDefaultAction(qact)
if not gprefs['search_tool_bar_shows_text']:
tb.setText(None)
else:
tb.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
self.addWidget(tb)
self.search_tool_bar_widgets.append(tb)
self.search_tool_bar_actions.append(qact)
self.setup_tool_button(self, qact, act.popup_type)
def widgetForAction(self, action):
dex = self.search_tool_bar_actions.index(action)
if dex < 0:
return None
return self.search_tool_bar_widgets[dex]
def setup_tool_button(self, bar, ac, menu_mode=None):
widget = self.widgetForAction(ac)
if widget is None:
return
widget.setCursor(Qt.CursorShape.PointingHandCursor)
if hasattr(widget, 'setAutoRaise'): # is a QToolButton or similar
widget.setAutoRaise(True)
m = ac.menu()
if m is not None:
if menu_mode is not None:
widget.setPopupMode(QToolButton.ToolButtonPopupMode(menu_mode))
return widget
def setIconSize(self, *args):
pass
def setToolButtonStyle(self, *args):
pass
def isVisible(self):
return True
def setVisible(self, toWhat):
pass
def update_lm_actions(self, *args):
pass
@property
def showing_donate(self):
return False
@property
def added_actions(self):
return self.search_tool_bar_actions
class BarsManager(QObject): class BarsManager(QObject):
def __init__(self, donate_action, location_manager, parent): def __init__(self, donate_action, location_manager, parent):
self.gui = parent
QObject.__init__(self, parent) QObject.__init__(self, parent)
self.location_manager = location_manager self.location_manager = location_manager
@ -630,7 +719,7 @@ class BarsManager(QObject):
self.main_bars = tuple(bars[:2]) self.main_bars = tuple(bars[:2])
self.child_bars = tuple(bars[2:]) self.child_bars = tuple(bars[2:])
self.reveal_bar = RevealBar(parent) self.reveal_bar = RevealBar(parent)
self.search_tool_bar = QHBoxLayout() self.search_tool_bar = SearchToolBar(parent)
self.menu_bar = MenuBar(self.location_manager, self.parent()) self.menu_bar = MenuBar(self.location_manager, self.parent())
is_native_menubar = self.menu_bar.is_native_menubar is_native_menubar = self.menu_bar.is_native_menubar
@ -647,7 +736,7 @@ class BarsManager(QObject):
@property @property
def bars(self): def bars(self):
yield from self.main_bars + self.child_bars yield from self.main_bars + self.child_bars + (self.search_tool_bar, )
@property @property
def showing_donate(self): def showing_donate(self):
@ -674,41 +763,7 @@ class BarsManager(QObject):
bar.init_bar(actions) bar.init_bar(actions)
# Build the layout containing the buttons to go into the search bar # Build the layout containing the buttons to go into the search bar
self.build_search_tool_bar() self.search_tool_bar.init_bar(gprefs['action-layout-searchbar'])
def build_search_tool_bar(self):
for ac in self.search_tool_bar_actions:
self.search_tool_bar.removeWidget(ac)
self.search_tool_bar.setContentsMargins(0, 0, 10, 0)
self.search_tool_bar.setSpacing(0)
self.search_tool_bar_actions = []
for what in gprefs['action-layout-searchbar']:
if what is None:
frame = QFrame()
frame.setFrameShape(QFrame.Shape.VLine)
frame.setFrameShadow(QFrame.Shadow.Sunken)
frame.setLineWidth(1)
frame.setContentsMargins(0, 5, 0, 5)
self.search_tool_bar.addWidget(frame)
self.search_tool_bar_actions.append(frame)
elif what in self.parent().iactions:
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']:
tb.setText(None)
else:
tb.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
tb.setCursor(Qt.CursorShape.PointingHandCursor)
tb.setPopupMode(act.popup_type)
tb.setAutoRaise(True)
self.search_tool_bar.addWidget(tb)
self.search_tool_bar_actions.append(tb)
def update_bars(self, reveal_bar=False): def update_bars(self, reveal_bar=False):
''' '''
@ -734,9 +789,7 @@ class BarsManager(QObject):
self.menu_bar.init_bar(self.bar_actions[4 if showing_device else 3]) self.menu_bar.init_bar(self.bar_actions[4 if showing_device else 3])
self.menu_bar.update_lm_actions() self.menu_bar.update_lm_actions()
self.menu_bar.setVisible(bool(self.menu_bar.added_actions)) self.menu_bar.setVisible(bool(self.menu_bar.added_actions))
self.build_search_tool_bar() # No need to update the Searchbar
from calibre.gui2.ui import get_gui
get_gui().search_bar.update()
def apply_settings(self): def apply_settings(self):
sz = gprefs['toolbar_icon_size'] sz = gprefs['toolbar_icon_size']

View File

@ -39,12 +39,12 @@ class BaseModel(QAbstractListModel):
if name == 'Donate': if name == 'Donate':
return FakeAction( return FakeAction(
'Donate', _('Donate'), 'donate.png', tooltip=_('Donate to support the development of calibre'), 'Donate', _('Donate'), 'donate.png', tooltip=_('Donate to support the development of calibre'),
dont_add_to=frozenset(['context-menu', 'context-menu-device'])) dont_add_to=frozenset(['context-menu', 'context-menu-device', 'searchbar']))
if name == 'Location Manager': if name == 'Location Manager':
return FakeAction('Location Manager', _('Location Manager'), 'reader.png', return FakeAction('Location Manager', _('Location Manager'), 'reader.png',
_('Switch between library and device views'), _('Switch between library and device views'),
dont_add_to=frozenset(['menubar', 'toolbar', dont_add_to=frozenset(['menubar', 'toolbar',
'toolbar-child', 'context-menu', 'toolbar-child', 'context-menu', 'searchbar',
'context-menu-device'])) 'context-menu-device']))
if name is None: if name is None:
return FakeAction('--- '+('Separator')+' ---', return FakeAction('--- '+('Separator')+' ---',