mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
49a2150b08
@ -522,12 +522,6 @@ content_server_thumbnail_compression_quality = 75
|
|||||||
# cover_drop_exclude = {'tiff', 'webp'}
|
# cover_drop_exclude = {'tiff', 'webp'}
|
||||||
cover_drop_exclude = ()
|
cover_drop_exclude = ()
|
||||||
|
|
||||||
#: Show the Saved searches box in the Search bar
|
|
||||||
# In newer versions of calibre, only a single button that allows you to add a
|
|
||||||
# new Saved search is shown in the Search bar. If you would like to have the
|
|
||||||
# old Saved searches box with its two buttons back, set this tweak to True.
|
|
||||||
show_saved_search_box = False
|
|
||||||
|
|
||||||
#: Exclude fields when copy/pasting metadata
|
#: Exclude fields when copy/pasting metadata
|
||||||
# You can ask calibre to not paste some metadata fields when using the
|
# You can ask calibre to not paste some metadata fields when using the
|
||||||
# Edit metadata->Copy metadata/Paste metadata actions. For example,
|
# Edit metadata->Copy metadata/Paste metadata actions. For example,
|
||||||
|
@ -284,6 +284,8 @@ def create_defs():
|
|||||||
|
|
||||||
defs['action-layout-toolbar-child'] = ()
|
defs['action-layout-toolbar-child'] = ()
|
||||||
|
|
||||||
|
defs['action-layout-searchbar'] = ('Saved searches',)
|
||||||
|
|
||||||
defs['action-layout-context-menu'] = (
|
defs['action-layout-context-menu'] = (
|
||||||
'Edit Metadata', 'Send To Device', 'Save To Disk',
|
'Edit Metadata', 'Send To Device', 'Save To Disk',
|
||||||
'Connect Share', 'Copy To Library', None,
|
'Connect Share', 'Copy To Library', None,
|
||||||
@ -395,6 +397,7 @@ def create_defs():
|
|||||||
defs['edit_metadata_templates_only_F2_on_booklist'] = False
|
defs['edit_metadata_templates_only_F2_on_booklist'] = False
|
||||||
# JSON dumps converts integer keys to strings, so do it explicitly
|
# JSON dumps converts integer keys to strings, so do it explicitly
|
||||||
defs['tb_search_order'] = {'0': 1, '1': 2, '2': 3, '3': 4, '4': 0}
|
defs['tb_search_order'] = {'0': 1, '1': 2, '2': 3, '3': 4, '4': 0}
|
||||||
|
defs['search_tool_bar_shows_text'] = True
|
||||||
|
|
||||||
def migrate_tweak(tweak_name, pref_name):
|
def migrate_tweak(tweak_name, pref_name):
|
||||||
# If the tweak has been changed then leave the tweak in the file so
|
# If the tweak has been changed then leave the tweak in the file so
|
||||||
|
@ -8,7 +8,8 @@ __docformat__ = 'restructuredtext en'
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from qt.core import (
|
from qt.core import (
|
||||||
Qt, QAction, QMenu, QObject, QToolBar, QToolButton, QSize, pyqtSignal, QKeySequence, QMenuBar,
|
Qt, QAction, QMenu, QObject, QToolBar, QToolButton, QSize, pyqtSignal, QKeySequence, QMenuBar,
|
||||||
QTimer, QPropertyAnimation, QEasingCurve, pyqtProperty, QPainter, QWidget, QPalette, sip)
|
QTimer, QPropertyAnimation, QEasingCurve, pyqtProperty, QPainter, QWidget, QPalette, sip,
|
||||||
|
QHBoxLayout, QFrame)
|
||||||
|
|
||||||
from calibre.constants import ismacos
|
from calibre.constants import ismacos
|
||||||
from calibre.gui2 import gprefs, native_menubar_defaults, config
|
from calibre.gui2 import gprefs, native_menubar_defaults, config
|
||||||
@ -628,6 +629,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.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
|
||||||
@ -636,6 +638,7 @@ class BarsManager(QObject):
|
|||||||
self.menubar_device_fallback = native_menubar_defaults['action-layout-menubar-device'] if is_native_menubar else ()
|
self.menubar_device_fallback = native_menubar_defaults['action-layout-menubar-device'] if is_native_menubar else ()
|
||||||
|
|
||||||
self.apply_settings()
|
self.apply_settings()
|
||||||
|
self.search_tool_bar_actions = []
|
||||||
self.init_bars()
|
self.init_bars()
|
||||||
|
|
||||||
def database_changed(self, db):
|
def database_changed(self, db):
|
||||||
@ -669,6 +672,41 @@ class BarsManager(QObject):
|
|||||||
for bar, actions in zip(self.bars, self.bar_actions[:3]):
|
for bar, actions in zip(self.bars, self.bar_actions[:3]):
|
||||||
bar.init_bar(actions)
|
bar.init_bar(actions)
|
||||||
|
|
||||||
|
# Build the layout containing the buttons to go into the search bar
|
||||||
|
self.build_search_tool_bar()
|
||||||
|
|
||||||
|
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, 0, 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:
|
||||||
|
qact = self.parent().iactions[what].qaction
|
||||||
|
tb = QToolButton()
|
||||||
|
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(QToolButton.ToolButtonPopupMode.InstantPopup)
|
||||||
|
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):
|
||||||
'''
|
'''
|
||||||
This shows the correct main toolbar and rebuilds the menubar based on
|
This shows the correct main toolbar and rebuilds the menubar based on
|
||||||
@ -693,6 +731,9 @@ 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()
|
||||||
|
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']
|
||||||
|
@ -14,8 +14,7 @@ from qt.core import (
|
|||||||
from calibre import human_readable
|
from calibre import human_readable
|
||||||
from calibre.constants import __appname__
|
from calibre.constants import __appname__
|
||||||
from calibre.gui2.bars import BarsManager
|
from calibre.gui2.bars import BarsManager
|
||||||
from calibre.gui2.search_box import SavedSearchBox, SearchBox2
|
from calibre.gui2.search_box import SearchBox2
|
||||||
from calibre.gui2.widgets2 import RightClickButton
|
|
||||||
from calibre.utils.config_base import tweaks
|
from calibre.utils.config_base import tweaks
|
||||||
|
|
||||||
|
|
||||||
@ -265,40 +264,8 @@ class SearchBar(QFrame): # {{{
|
|||||||
x.setIcon(QIcon.ic('arrow-down.png'))
|
x.setIcon(QIcon.ic('arrow-down.png'))
|
||||||
l.addWidget(x)
|
l.addWidget(x)
|
||||||
|
|
||||||
x = parent.saved_search = SavedSearchBox(self)
|
# Add the searchbar tool buttons to the bar
|
||||||
x.setObjectName("saved_search")
|
l.addLayout(self.parent().bars_manager.search_tool_bar)
|
||||||
l.addWidget(x)
|
|
||||||
x.setVisible(tweaks['show_saved_search_box'])
|
|
||||||
|
|
||||||
x = parent.copy_search_button = QToolButton(self)
|
|
||||||
x.setAutoRaise(True)
|
|
||||||
x.setCursor(Qt.CursorShape.PointingHandCursor)
|
|
||||||
x.setIcon(QIcon.ic("search_copy_saved.png"))
|
|
||||||
x.setObjectName("copy_search_button")
|
|
||||||
l.addWidget(x)
|
|
||||||
x.setToolTip(_("Copy current search text (instead of search name)"))
|
|
||||||
x.setVisible(tweaks['show_saved_search_box'])
|
|
||||||
|
|
||||||
x = parent.save_search_button = RightClickButton(self)
|
|
||||||
x.setAutoRaise(True)
|
|
||||||
x.setCursor(Qt.CursorShape.PointingHandCursor)
|
|
||||||
x.setIcon(QIcon.ic("search_add_saved.png"))
|
|
||||||
x.setObjectName("save_search_button")
|
|
||||||
l.addWidget(x)
|
|
||||||
x.setVisible(tweaks['show_saved_search_box'])
|
|
||||||
|
|
||||||
x = parent.add_saved_search_button = RightClickButton(self)
|
|
||||||
x.setToolTip(_(
|
|
||||||
'Use an existing Saved search or create a new one'
|
|
||||||
))
|
|
||||||
x.setText(_('Saved search'))
|
|
||||||
x.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
|
||||||
x.setCursor(Qt.CursorShape.PointingHandCursor)
|
|
||||||
x.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
|
||||||
x.setAutoRaise(True)
|
|
||||||
x.setIcon(QIcon.ic("folder_saved_search.png"))
|
|
||||||
l.addWidget(x)
|
|
||||||
x.setVisible(not tweaks['show_saved_search_box'])
|
|
||||||
|
|
||||||
def populate_sort_menu(self):
|
def populate_sort_menu(self):
|
||||||
from calibre.gui2.ui import get_gui
|
from calibre.gui2.ui import get_gui
|
||||||
@ -342,9 +309,10 @@ class MainWindowMixin: # {{{
|
|||||||
|
|
||||||
self.iactions['Fetch News'].init_scheduler()
|
self.iactions['Fetch News'].init_scheduler()
|
||||||
|
|
||||||
self.search_bar = SearchBar(self)
|
|
||||||
self.bars_manager = BarsManager(self.donate_action,
|
self.bars_manager = BarsManager(self.donate_action,
|
||||||
self.location_manager, self)
|
self.location_manager, self)
|
||||||
|
# instantiating SearchBar must happen after setting bars manager
|
||||||
|
self.search_bar = SearchBar(self)
|
||||||
for bar in self.bars_manager.main_bars:
|
for bar in self.bars_manager.main_bars:
|
||||||
self.addToolBar(Qt.ToolBarArea.TopToolBarArea, bar)
|
self.addToolBar(Qt.ToolBarArea.TopToolBarArea, bar)
|
||||||
bar.setStyleSheet('QToolBar { border: 0px }')
|
bar.setStyleSheet('QToolBar { border: 0px }')
|
||||||
|
@ -32,6 +32,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
r('show_highlight_toggle_button', gprefs)
|
r('show_highlight_toggle_button', gprefs)
|
||||||
r('limit_search_columns', prefs)
|
r('limit_search_columns', prefs)
|
||||||
r('use_primary_find_in_search', prefs)
|
r('use_primary_find_in_search', prefs)
|
||||||
|
r('search_tool_bar_shows_text', gprefs)
|
||||||
r('case_sensitive', prefs)
|
r('case_sensitive', prefs)
|
||||||
fl = db.field_metadata.get_search_terms()
|
fl = db.field_metadata.get_search_terms()
|
||||||
r('limit_search_columns_to', prefs, setting=CommaSeparatedList, choices=fl)
|
r('limit_search_columns_to', prefs, setting=CommaSeparatedList, choices=fl)
|
||||||
@ -236,6 +237,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
return ConfigWidgetBase.commit(self)
|
return ConfigWidgetBase.commit(self)
|
||||||
|
|
||||||
def refresh_gui(self, gui):
|
def refresh_gui(self, gui):
|
||||||
|
gui.refresh_search_bar_widgets()
|
||||||
gui.current_db.new_api.clear_caches()
|
gui.current_db.new_api.clear_caches()
|
||||||
set_use_primary_find_in_search(prefs['use_primary_find_in_search'])
|
set_use_primary_find_in_search(prefs['use_primary_find_in_search'])
|
||||||
gui.set_highlight_only_button_icon()
|
gui.set_highlight_only_button_icon()
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<string>Genera&l</string>
|
<string>Genera&l</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" name="gridLayout_6">
|
<layout class="QGridLayout" name="gridLayout_6">
|
||||||
<item row="6" column="0">
|
<item row="11" column="0">
|
||||||
<widget class="QPushButton" name="clear_history_button">
|
<widget class="QPushButton" name="clear_history_button">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
@ -40,7 +40,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0" colspan="2">
|
<item row="10" column="0" colspan="2">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>What to search by default</string>
|
<string>What to search by default</string>
|
||||||
@ -120,7 +120,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="20" column="0">
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -140,6 +140,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QCheckBox" name="opt_search_tool_bar_shows_text">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show text next to buttons in the search bar</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_2">
|
<widget class="QWidget" name="tab_2">
|
||||||
|
@ -245,6 +245,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
('toolbar', _('The main toolbar')),
|
('toolbar', _('The main toolbar')),
|
||||||
('toolbar-device', _('The main toolbar when a device is connected')),
|
('toolbar-device', _('The main toolbar when a device is connected')),
|
||||||
('toolbar-child', _('The optional second toolbar')),
|
('toolbar-child', _('The optional second toolbar')),
|
||||||
|
('searchbar', ('The buttons on the search bar')),
|
||||||
('menubar', _('The menubar')),
|
('menubar', _('The menubar')),
|
||||||
('menubar-device', _('The menubar when a device is connected')),
|
('menubar-device', _('The menubar when a device is connected')),
|
||||||
('context-menu', _('The context menu for the books in the '
|
('context-menu', _('The context menu for the books in the '
|
||||||
|
@ -12,10 +12,9 @@ from functools import partial
|
|||||||
from qt.core import (
|
from qt.core import (
|
||||||
QComboBox, Qt, QLineEdit, pyqtSlot, QDialog, QEvent,
|
QComboBox, Qt, QLineEdit, pyqtSlot, QDialog, QEvent,
|
||||||
pyqtSignal, QCompleter, QAction, QKeySequence, QTimer,
|
pyqtSignal, QCompleter, QAction, QKeySequence, QTimer,
|
||||||
QIcon, QMenu, QApplication, QKeyEvent)
|
QIcon, QApplication, QKeyEvent)
|
||||||
|
|
||||||
from calibre.gui2 import config, error_dialog, question_dialog, gprefs, QT_HIDDEN_CLEAR_ACTION
|
from calibre.gui2 import config, question_dialog, gprefs, QT_HIDDEN_CLEAR_ACTION
|
||||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
|
||||||
from calibre.gui2.dialogs.saved_search_editor import SavedSearchEditor
|
from calibre.gui2.dialogs.saved_search_editor import SavedSearchEditor
|
||||||
from calibre.gui2.dialogs.search import SearchDialog
|
from calibre.gui2.dialogs.search import SearchDialog
|
||||||
from calibre.utils.icu import primary_sort_key
|
from calibre.utils.icu import primary_sort_key
|
||||||
@ -320,147 +319,6 @@ class SearchBox2(QComboBox): # {{{
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
class SavedSearchBox(QComboBox): # {{{
|
|
||||||
|
|
||||||
'''
|
|
||||||
To use this class:
|
|
||||||
* Call initialize()
|
|
||||||
* Connect to the changed() signal from this widget
|
|
||||||
if you care about changes to the list of saved searches.
|
|
||||||
'''
|
|
||||||
|
|
||||||
changed = pyqtSignal()
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
QComboBox.__init__(self, parent)
|
|
||||||
|
|
||||||
self.line_edit = SearchLineEdit(self)
|
|
||||||
self.setLineEdit(self.line_edit)
|
|
||||||
self.line_edit.key_pressed.connect(self.key_pressed, type=Qt.ConnectionType.DirectConnection)
|
|
||||||
self.textActivated.connect(self.saved_search_selected)
|
|
||||||
|
|
||||||
# Turn off auto-completion so that it doesn't interfere with typing
|
|
||||||
# names of new searches.
|
|
||||||
completer = QCompleter(self)
|
|
||||||
self.setCompleter(completer)
|
|
||||||
|
|
||||||
self.setEditable(True)
|
|
||||||
self.setMaxVisibleItems(25)
|
|
||||||
self.setInsertPolicy(QComboBox.InsertPolicy.NoInsert)
|
|
||||||
self.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon)
|
|
||||||
self.setMinimumContentsLength(25)
|
|
||||||
self.tool_tip_text = self.toolTip()
|
|
||||||
|
|
||||||
def initialize(self, _search_box, colorize=False, help_text=_('Search')):
|
|
||||||
self.search_box = _search_box
|
|
||||||
try:
|
|
||||||
self.line_edit.setPlaceholderText(help_text)
|
|
||||||
except:
|
|
||||||
# Using Qt < 4.7
|
|
||||||
pass
|
|
||||||
self.colorize = colorize
|
|
||||||
self.clear()
|
|
||||||
|
|
||||||
def normalize_state(self):
|
|
||||||
# need this because line_edit will call it in some cases such as paste
|
|
||||||
pass
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
QComboBox.clear(self)
|
|
||||||
self.initialize_saved_search_names()
|
|
||||||
self.setEditText('')
|
|
||||||
self.setToolTip(self.tool_tip_text)
|
|
||||||
self.line_edit.home(False)
|
|
||||||
|
|
||||||
def key_pressed(self, event):
|
|
||||||
if event.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter):
|
|
||||||
self.saved_search_selected(self.currentText())
|
|
||||||
|
|
||||||
def saved_search_selected(self, qname):
|
|
||||||
from calibre.gui2.ui import get_gui
|
|
||||||
db = get_gui().current_db
|
|
||||||
qname = str(qname)
|
|
||||||
if qname is None or not qname.strip():
|
|
||||||
self.search_box.clear()
|
|
||||||
return
|
|
||||||
if not db.saved_search_lookup(qname):
|
|
||||||
self.search_box.clear()
|
|
||||||
self.setEditText(qname)
|
|
||||||
return
|
|
||||||
self.search_box.set_search_string('search:"%s"' % qname, emit_changed=False)
|
|
||||||
self.setEditText(qname)
|
|
||||||
self.setToolTip(db.saved_search_lookup(qname))
|
|
||||||
|
|
||||||
def initialize_saved_search_names(self):
|
|
||||||
from calibre.gui2.ui import get_gui
|
|
||||||
gui = get_gui()
|
|
||||||
try:
|
|
||||||
names = gui.current_db.saved_search_names()
|
|
||||||
except AttributeError:
|
|
||||||
# Happens during gui initialization
|
|
||||||
names = []
|
|
||||||
self.addItems(names)
|
|
||||||
self.setCurrentIndex(-1)
|
|
||||||
|
|
||||||
# SIGNALed from the main UI
|
|
||||||
def save_search_button_clicked(self):
|
|
||||||
from calibre.gui2.ui import get_gui
|
|
||||||
db = get_gui().current_db
|
|
||||||
name = str(self.currentText())
|
|
||||||
if not name.strip():
|
|
||||||
name = str(self.search_box.text()).replace('"', '')
|
|
||||||
name = name.replace('\\', '')
|
|
||||||
if not name:
|
|
||||||
error_dialog(self, _('Create saved search'),
|
|
||||||
_('Invalid saved search name. '
|
|
||||||
'It must contain at least one letter or number'), show=True)
|
|
||||||
return
|
|
||||||
if not self.search_box.text():
|
|
||||||
error_dialog(self, _('Create saved search'),
|
|
||||||
_('There is no search to save'), show=True)
|
|
||||||
return
|
|
||||||
db.saved_search_delete(name)
|
|
||||||
db.saved_search_add(name, str(self.search_box.text()))
|
|
||||||
# now go through an initialization cycle to ensure that the combobox has
|
|
||||||
# the new search in it, that it is selected, and that the search box
|
|
||||||
# references the new search instead of the text in the search.
|
|
||||||
self.clear()
|
|
||||||
self.setCurrentIndex(self.findText(name))
|
|
||||||
self.saved_search_selected(name)
|
|
||||||
self.changed.emit()
|
|
||||||
|
|
||||||
def delete_current_search(self):
|
|
||||||
from calibre.gui2.ui import get_gui
|
|
||||||
db = get_gui().current_db
|
|
||||||
idx = self.currentIndex()
|
|
||||||
if idx <= 0:
|
|
||||||
error_dialog(self, _('Delete current search'),
|
|
||||||
_('No search is selected'), show=True)
|
|
||||||
return
|
|
||||||
if not confirm('<p>'+_('The selected search will be '
|
|
||||||
'<b>permanently deleted</b>. Are you sure?') +
|
|
||||||
'</p>', 'saved_search_delete', self):
|
|
||||||
return
|
|
||||||
ss = db.saved_search_lookup(str(self.currentText()))
|
|
||||||
if ss is None:
|
|
||||||
return
|
|
||||||
db.saved_search_delete(str(self.currentText()))
|
|
||||||
self.clear()
|
|
||||||
self.search_box.clear()
|
|
||||||
self.changed.emit()
|
|
||||||
|
|
||||||
# SIGNALed from the main UI
|
|
||||||
def copy_search_button_clicked(self):
|
|
||||||
from calibre.gui2.ui import get_gui
|
|
||||||
db = get_gui().current_db
|
|
||||||
idx = self.currentIndex()
|
|
||||||
if idx < 0:
|
|
||||||
return
|
|
||||||
self.search_box.set_search_string(db.saved_search_lookup(str(self.currentText())))
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
|
|
||||||
class SearchBoxMixin: # {{{
|
class SearchBoxMixin: # {{{
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@ -497,6 +355,16 @@ class SearchBoxMixin: # {{{
|
|||||||
self.highlight_only_action = ac = QAction(self)
|
self.highlight_only_action = ac = QAction(self)
|
||||||
self.addAction(ac), ac.triggered.connect(self.highlight_only_clicked)
|
self.addAction(ac), ac.triggered.connect(self.highlight_only_clicked)
|
||||||
self.keyboard.register_shortcut('highlight search results', _('Highlight search results'), action=self.highlight_only_action)
|
self.keyboard.register_shortcut('highlight search results', _('Highlight search results'), action=self.highlight_only_action)
|
||||||
|
self.refresh_search_bar_widgets()
|
||||||
|
|
||||||
|
def refresh_search_bar_widgets(self):
|
||||||
|
self.set_highlight_only_button_icon()
|
||||||
|
if gprefs['search_tool_bar_shows_text']:
|
||||||
|
self.search_bar.search_button.setText(_('Search'))
|
||||||
|
self.search_bar.search_button.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
||||||
|
else:
|
||||||
|
self.search_bar.search_button.setText(None)
|
||||||
|
self.search_bar.search_button.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||||
|
|
||||||
def highlight_only_clicked(self, state):
|
def highlight_only_clicked(self, state):
|
||||||
if not config['highlight_search_matches'] and not question_dialog(self, _('Are you sure?'),
|
if not config['highlight_search_matches'] and not question_dialog(self, _('Are you sure?'),
|
||||||
@ -513,10 +381,20 @@ class SearchBoxMixin: # {{{
|
|||||||
b = self.highlight_only_button
|
b = self.highlight_only_button
|
||||||
if config['highlight_search_matches']:
|
if config['highlight_search_matches']:
|
||||||
b.setIcon(QIcon.ic('highlight_only_on.png'))
|
b.setIcon(QIcon.ic('highlight_only_on.png'))
|
||||||
b.setText(_('Filter'))
|
if gprefs['search_tool_bar_shows_text']:
|
||||||
|
b.setText(_('Filter'))
|
||||||
|
b.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
||||||
|
else:
|
||||||
|
b.setText(None)
|
||||||
|
b.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||||
else:
|
else:
|
||||||
b.setIcon(QIcon.ic('highlight_only_off.png'))
|
b.setIcon(QIcon.ic('highlight_only_off.png'))
|
||||||
b.setText(_('Highlight'))
|
if gprefs['search_tool_bar_shows_text']:
|
||||||
|
b.setText(_('Highlight'))
|
||||||
|
b.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
||||||
|
else:
|
||||||
|
b.setText(None)
|
||||||
|
b.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||||
self.highlight_only_button.setVisible(gprefs['show_highlight_toggle_button'])
|
self.highlight_only_button.setVisible(gprefs['show_highlight_toggle_button'])
|
||||||
self.library_view.model().set_highlight_only(config['highlight_search_matches'])
|
self.library_view.model().set_highlight_only(config['highlight_search_matches'])
|
||||||
|
|
||||||
@ -526,11 +404,9 @@ class SearchBoxMixin: # {{{
|
|||||||
|
|
||||||
def search_box_cleared(self):
|
def search_box_cleared(self):
|
||||||
self.tags_view.clear()
|
self.tags_view.clear()
|
||||||
self.saved_search.clear()
|
|
||||||
self.set_number_of_books_shown()
|
self.set_number_of_books_shown()
|
||||||
|
|
||||||
def search_box_changed(self):
|
def search_box_changed(self):
|
||||||
self.saved_search.clear()
|
|
||||||
self.tags_view.conditional_clear(self.search.current_text)
|
self.tags_view.conditional_clear(self.search.current_text)
|
||||||
|
|
||||||
def do_advanced_search(self, *args):
|
def do_advanced_search(self, *args):
|
||||||
@ -554,41 +430,10 @@ class SavedSearchBoxMixin: # {{{
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def init_saved_seach_box_mixin(self):
|
def init_saved_seach_box_mixin(self):
|
||||||
self.saved_search.changed.connect(self.saved_searches_changed)
|
pass
|
||||||
ac = self.search.findChild(QAction, QT_HIDDEN_CLEAR_ACTION)
|
|
||||||
if ac is not None:
|
|
||||||
ac.triggered.connect(self.saved_search.clear)
|
|
||||||
self.save_search_button.clicked.connect(
|
|
||||||
self.saved_search.save_search_button_clicked)
|
|
||||||
self.copy_search_button.clicked.connect(
|
|
||||||
self.saved_search.copy_search_button_clicked)
|
|
||||||
# self.saved_searches_changed()
|
|
||||||
self.saved_search.initialize(self.search, colorize=True,
|
|
||||||
help_text=_('Saved searches'))
|
|
||||||
self.saved_search.tool_tip_text=_('Choose saved search or enter name for new saved search')
|
|
||||||
self.saved_search.setToolTip(self.saved_search.tool_tip_text)
|
|
||||||
self.saved_search.setStatusTip(self.saved_search.tool_tip_text)
|
|
||||||
for x in ('copy', 'save'):
|
|
||||||
b = getattr(self, x+'_search_button')
|
|
||||||
b.setStatusTip(b.toolTip())
|
|
||||||
self.save_search_button.setToolTip('<p>' +
|
|
||||||
_("Save current search under the name shown in the box. "
|
|
||||||
"Press and hold for a pop-up options menu.") + '</p>')
|
|
||||||
self.save_search_button.setMenu(QMenu(self.save_search_button))
|
|
||||||
self.save_search_button.menu().addAction(
|
|
||||||
QIcon.ic('search_add_saved.png'),
|
|
||||||
_('Create Saved search'),
|
|
||||||
self.saved_search.save_search_button_clicked)
|
|
||||||
self.save_search_button.menu().addAction(
|
|
||||||
QIcon.ic('search_delete_saved.png'), _('Delete Saved search'), self.saved_search.delete_current_search)
|
|
||||||
self.save_search_button.menu().addAction(
|
|
||||||
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.menu().aboutToShow.connect(self.populate_add_saved_search_menu)
|
|
||||||
|
|
||||||
|
def populate_add_saved_search_menu(self, to_menu):
|
||||||
def populate_add_saved_search_menu(self, to_menu=None):
|
m = to_menu
|
||||||
m = to_menu if to_menu is not None else self.add_saved_search_button.menu()
|
|
||||||
m.clear()
|
m.clear()
|
||||||
m.clear()
|
m.clear()
|
||||||
m.addAction(QIcon.ic('search_add_saved.png'), _('Add Saved search'), self.add_saved_search)
|
m.addAction(QIcon.ic('search_add_saved.png'), _('Add Saved search'), self.add_saved_search)
|
||||||
@ -631,7 +476,6 @@ class SavedSearchBoxMixin: # {{{
|
|||||||
|
|
||||||
def do_rebuild_saved_searches(self):
|
def do_rebuild_saved_searches(self):
|
||||||
self.saved_searches_changed()
|
self.saved_searches_changed()
|
||||||
self.saved_search.clear()
|
|
||||||
|
|
||||||
def add_saved_search(self):
|
def add_saved_search(self):
|
||||||
from calibre.gui2.dialogs.saved_search_editor import AddSavedSearch
|
from calibre.gui2.dialogs.saved_search_editor import AddSavedSearch
|
||||||
|
Loading…
x
Reference in New Issue
Block a user