mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
15d41840f5
@ -1,7 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# License: GPLv3 Copyright: 2022, Charles Haley
|
# License: GPLv3 Copyright: 2022, Charles Haley
|
||||||
#
|
#
|
||||||
from qt.core import QPoint
|
|
||||||
|
|
||||||
from calibre.gui2.actions import InterfaceAction
|
from calibre.gui2.actions import InterfaceAction
|
||||||
|
|
||||||
@ -29,25 +28,8 @@ class ManageCategoriesAction(InterfaceAction):
|
|||||||
# show the menu in the upper left corner of the library view pane. Yes, this
|
# show the menu in the upper left corner of the library view pane. Yes, this
|
||||||
# is a bit weird but it works as well as a popping up a dialog.
|
# is a bit weird but it works as well as a popping up a dialog.
|
||||||
def show_menu(self):
|
def show_menu(self):
|
||||||
for x in self.gui.bars_manager.main_bars + self.gui.bars_manager.child_bars:
|
from calibre.gui2.actions.saved_searches import show_menu_under_widget
|
||||||
try:
|
show_menu_under_widget(self.gui, self.menu, self.qaction, self.name)
|
||||||
w = x.widgetForAction(self.qaction)
|
|
||||||
# It seems that multiple copies of the action can exist, such as
|
|
||||||
# when the device-connected menu is changed while the device is
|
|
||||||
# connected. Use the one that has an actual position.
|
|
||||||
if w.pos().x() == 0:
|
|
||||||
continue
|
|
||||||
# The button might be hidden
|
|
||||||
if not w.isVisible():
|
|
||||||
continue
|
|
||||||
# The w.height() assures that the menu opens below the button.
|
|
||||||
self.menu.exec(w.mapToGlobal(QPoint(0, w.height())))
|
|
||||||
return
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
# No visible button found. Fall back to displaying in upper left corner
|
|
||||||
# of the library view.
|
|
||||||
self.menu.exec(self.gui.library_view.mapToGlobal(QPoint(10, 10)))
|
|
||||||
|
|
||||||
def about_to_show_menu(self):
|
def about_to_show_menu(self):
|
||||||
db = self.gui.current_db
|
db = self.gui.current_db
|
||||||
|
@ -1,12 +1,56 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# License: GPLv3 Copyright: 2022, Charles Haley
|
# License: GPLv3 Copyright: 2022, Charles Haley
|
||||||
#
|
#
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
from qt.core import QPoint, QIcon
|
from qt.core import QPoint
|
||||||
|
|
||||||
from calibre.gui2.actions import InterfaceAction
|
from calibre.gui2.actions import InterfaceAction
|
||||||
from calibre.utils.icu import primary_sort_key
|
|
||||||
|
|
||||||
|
def show_menu_under_widget(gui, menu, action, name):
|
||||||
|
# First try the tool bar
|
||||||
|
for x in gui.bars_manager.main_bars + gui.bars_manager.child_bars:
|
||||||
|
try:
|
||||||
|
w = x.widgetForAction(action)
|
||||||
|
# It seems that multiple copies of the action can exist, such as
|
||||||
|
# when the device-connected menu is changed while the device is
|
||||||
|
# connected. Use the one that has an actual position.
|
||||||
|
if w.pos().x() == 0:
|
||||||
|
continue
|
||||||
|
# The button might be hidden
|
||||||
|
if not w.isVisible():
|
||||||
|
continue
|
||||||
|
# The w.height() assures that the menu opens below the button.
|
||||||
|
menu.exec(w.mapToGlobal(QPoint(0, w.height())))
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
# Now try the menu bar
|
||||||
|
for x in gui.bars_manager.menu_bar.added_actions:
|
||||||
|
# This depends on no two menus with the same name.
|
||||||
|
# I don't know if this works on a Mac
|
||||||
|
if x.text() == name:
|
||||||
|
try:
|
||||||
|
# The menu item might be hidden
|
||||||
|
if not x.isVisible():
|
||||||
|
continue
|
||||||
|
# We can't use x.trigger() because it doesn't put the menu
|
||||||
|
# in the right place. Instead get the position of the menu
|
||||||
|
# widget on the menu bar
|
||||||
|
p = x.parent().menu_bar
|
||||||
|
r = p.actionGeometry(x)
|
||||||
|
# Make sure that the menu item is actually displayed in the menu
|
||||||
|
# and not the overflow
|
||||||
|
if p.geometry().width() < (r.x() + r.width()):
|
||||||
|
continue
|
||||||
|
# Show the menu under the name in the menu bar
|
||||||
|
menu.exec(p.mapToGlobal(QPoint(r.x()+2, r.height()-2)))
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
# 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)))
|
||||||
|
|
||||||
|
|
||||||
class SavedSearchesAction(InterfaceAction):
|
class SavedSearchesAction(InterfaceAction):
|
||||||
@ -32,47 +76,10 @@ class SavedSearchesAction(InterfaceAction):
|
|||||||
# show the menu in the upper left corner of the library view pane. Yes, this
|
# show the menu in the upper left corner of the library view pane. Yes, this
|
||||||
# is a bit weird but it works as well as a popping up a dialog.
|
# is a bit weird but it works as well as a popping up a dialog.
|
||||||
def show_menu(self):
|
def show_menu(self):
|
||||||
for x in self.gui.bars_manager.main_bars + self.gui.bars_manager.child_bars:
|
show_menu_under_widget(self.gui, self.menu, self.qaction, self.name)
|
||||||
try:
|
|
||||||
w = x.widgetForAction(self.qaction)
|
|
||||||
# It seems that multiple copies of the action can exist, such as
|
|
||||||
# when the device-connected menu is changed while the device is
|
|
||||||
# connected. Use the one that has an actual position.
|
|
||||||
if w.pos().x() == 0:
|
|
||||||
continue
|
|
||||||
# The button might be hidden
|
|
||||||
if not w.isVisible():
|
|
||||||
continue
|
|
||||||
# The w.height() assures that the menu opens below the button.
|
|
||||||
self.menu.exec(w.mapToGlobal(QPoint(0, w.height())))
|
|
||||||
return
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
# No visible button found. Fall back to displaying in upper left corner
|
|
||||||
# of the library view.
|
|
||||||
self.menu.exec(self.gui.library_view.mapToGlobal(QPoint(10, 10)))
|
|
||||||
|
|
||||||
def about_to_show_menu(self):
|
def about_to_show_menu(self):
|
||||||
db = self.gui.current_db
|
self.gui.populate_add_saved_search_menu(to_menu=self.menu)
|
||||||
m = self.menu
|
|
||||||
m.clear()
|
|
||||||
submenus = {}
|
|
||||||
for name in sorted(db.saved_search_names(), key=lambda x: primary_sort_key(x.strip())):
|
|
||||||
components = tuple(n.strip() for n in name.split('.'))
|
|
||||||
hierarchy = components[:-1]
|
|
||||||
last = components[-1]
|
|
||||||
current_menu = m
|
|
||||||
# Walk the hierarchy, creating submenus as needed
|
|
||||||
for i,c in enumerate(hierarchy, start=1):
|
|
||||||
hierarchical_prefix = '.'.join(hierarchy[:i])
|
|
||||||
if hierarchical_prefix not in submenus:
|
|
||||||
current_menu = current_menu.addMenu(c)
|
|
||||||
current_menu.setIcon(QIcon.ic('folder_saved_search.png'))
|
|
||||||
submenus[hierarchical_prefix] = current_menu
|
|
||||||
else:
|
|
||||||
current_menu = submenus[hierarchical_prefix]
|
|
||||||
ac = current_menu.addAction(last, partial(self.gui.search.set_search_string, 'search:"='+name+'"'))
|
|
||||||
ac.setIcon(QIcon.ic('search.png'))
|
|
||||||
|
|
||||||
def location_selected(self, loc):
|
def location_selected(self, loc):
|
||||||
enabled = loc == 'library'
|
enabled = loc == 'library'
|
||||||
|
@ -100,11 +100,11 @@ class SavedSearchEditor(Dialog):
|
|||||||
db = get_gui().current_db
|
db = get_gui().current_db
|
||||||
self.l = l = QVBoxLayout(self)
|
self.l = l = QVBoxLayout(self)
|
||||||
b = self.bb.addButton(_('&Add search'), QDialogButtonBox.ButtonRole.ActionRole)
|
b = self.bb.addButton(_('&Add search'), QDialogButtonBox.ButtonRole.ActionRole)
|
||||||
b.setIcon(QIcon.ic('plus.png'))
|
b.setIcon(QIcon.ic('search_add_saved.png'))
|
||||||
b.clicked.connect(self.add_search)
|
b.clicked.connect(self.add_search)
|
||||||
|
|
||||||
b = self.bb.addButton(_('&Remove search'), QDialogButtonBox.ButtonRole.ActionRole)
|
b = self.bb.addButton(_('&Remove search'), QDialogButtonBox.ButtonRole.ActionRole)
|
||||||
b.setIcon(QIcon.ic('minus.png'))
|
b.setIcon(QIcon.ic('search_delete_saved.png'))
|
||||||
b.clicked.connect(self.del_search)
|
b.clicked.connect(self.del_search)
|
||||||
|
|
||||||
b = self.bb.addButton(_('&Edit search'), QDialogButtonBox.ButtonRole.ActionRole)
|
b = self.bb.addButton(_('&Edit search'), QDialogButtonBox.ButtonRole.ActionRole)
|
||||||
|
@ -296,7 +296,7 @@ class SearchBar(QFrame): # {{{
|
|||||||
x.setCursor(Qt.CursorShape.PointingHandCursor)
|
x.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
x.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
x.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
||||||
x.setAutoRaise(True)
|
x.setAutoRaise(True)
|
||||||
x.setIcon(QIcon.ic("bookmarks.png"))
|
x.setIcon(QIcon.ic("folder_saved_search.png"))
|
||||||
l.addWidget(x)
|
l.addWidget(x)
|
||||||
x.setVisible(not tweaks['show_saved_search_box'])
|
x.setVisible(not tweaks['show_saved_search_box'])
|
||||||
|
|
||||||
|
@ -576,27 +576,45 @@ class SavedSearchBoxMixin: # {{{
|
|||||||
"Press and hold for a pop-up options menu.") + '</p>')
|
"Press and hold for a pop-up options menu.") + '</p>')
|
||||||
self.save_search_button.setMenu(QMenu(self.save_search_button))
|
self.save_search_button.setMenu(QMenu(self.save_search_button))
|
||||||
self.save_search_button.menu().addAction(
|
self.save_search_button.menu().addAction(
|
||||||
QIcon.ic('plus.png'),
|
QIcon.ic('search_add_saved.png'),
|
||||||
_('Create Saved search'),
|
_('Create Saved search'),
|
||||||
self.saved_search.save_search_button_clicked)
|
self.saved_search.save_search_button_clicked)
|
||||||
self.save_search_button.menu().addAction(
|
self.save_search_button.menu().addAction(
|
||||||
QIcon.ic('trash.png'), _('Delete Saved search'), self.saved_search.delete_current_search)
|
QIcon.ic('search_delete_saved.png'), _('Delete Saved search'), self.saved_search.delete_current_search)
|
||||||
self.save_search_button.menu().addAction(
|
self.save_search_button.menu().addAction(
|
||||||
QIcon.ic('search.png'), _('Manage Saved searches'), partial(self.do_saved_search_edit, None))
|
QIcon.ic('search.png'), _('Manage Saved searches'), partial(self.do_saved_search_edit, None))
|
||||||
self.add_saved_search_button.setMenu(QMenu(self.add_saved_search_button))
|
self.add_saved_search_button.setMenu(QMenu(self.add_saved_search_button))
|
||||||
self.add_saved_search_button.menu().aboutToShow.connect(self.populate_add_saved_search_menu)
|
self.add_saved_search_button.menu().aboutToShow.connect(self.populate_add_saved_search_menu)
|
||||||
|
|
||||||
def populate_add_saved_search_menu(self):
|
|
||||||
m = self.add_saved_search_button.menu()
|
def populate_add_saved_search_menu(self, to_menu=None):
|
||||||
|
m = to_menu if to_menu is not None else self.add_saved_search_button.menu()
|
||||||
m.clear()
|
m.clear()
|
||||||
m.addAction(QIcon.ic('plus.png'), _('Add Saved search'), self.add_saved_search)
|
m.clear()
|
||||||
m.addAction(QIcon.ic("search_copy_saved.png"), _('Get Saved search expression'),
|
m.addAction(QIcon.ic('search_add_saved.png'), _('Add Saved search'), self.add_saved_search)
|
||||||
self.get_saved_search_text)
|
m.addAction(QIcon.ic('search_copy_saved.png'), _('Get Saved search expression'),
|
||||||
m.addActions(list(self.save_search_button.menu().actions())[-1:])
|
self.get_saved_search_text)
|
||||||
|
m.addAction(QIcon.ic('folder_saved_search.png'), _('Manage Saved searches'),
|
||||||
|
partial(self.do_saved_search_edit, None))
|
||||||
m.addSeparator()
|
m.addSeparator()
|
||||||
db = self.current_db
|
db = self.current_db
|
||||||
|
submenus = {}
|
||||||
for name in sorted(db.saved_search_names(), key=lambda x: primary_sort_key(x.strip())):
|
for name in sorted(db.saved_search_names(), key=lambda x: primary_sort_key(x.strip())):
|
||||||
m.addAction(name.strip(), partial(self.saved_search.saved_search_selected, name))
|
components = tuple(n.strip() for n in name.split('.'))
|
||||||
|
hierarchy = components[:-1]
|
||||||
|
last = components[-1]
|
||||||
|
current_menu = m
|
||||||
|
# Walk the hierarchy, creating submenus as needed
|
||||||
|
for i,c in enumerate(hierarchy, start=1):
|
||||||
|
hierarchical_prefix = '.'.join(hierarchy[:i])
|
||||||
|
if hierarchical_prefix not in submenus:
|
||||||
|
current_menu = current_menu.addMenu(c)
|
||||||
|
current_menu.setIcon(QIcon.ic('folder_saved_search.png'))
|
||||||
|
submenus[hierarchical_prefix] = current_menu
|
||||||
|
else:
|
||||||
|
current_menu = submenus[hierarchical_prefix]
|
||||||
|
ac = current_menu.addAction(last, partial(self.search.set_search_string, 'search:"='+name+'"'))
|
||||||
|
ac.setIcon(QIcon.ic('search.png'))
|
||||||
|
|
||||||
def saved_searches_changed(self, set_restriction=None, recount=True):
|
def saved_searches_changed(self, set_restriction=None, recount=True):
|
||||||
self.build_search_restriction_list()
|
self.build_search_restriction_list()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user