mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Start work on search panel
This commit is contained in:
parent
90eb2c43f0
commit
8db373d3b5
@ -140,8 +140,8 @@ class SearchBox2(QComboBox): # {{{
|
||||
icon = QIcon(I(icon))
|
||||
return self.lineEdit().addAction(icon, position)
|
||||
|
||||
def initialize(self, opt_name, colorize=False, help_text=_('Search')):
|
||||
self.as_you_type = config['search_as_you_type']
|
||||
def initialize(self, opt_name, colorize=False, help_text=_('Search'), as_you_type=None):
|
||||
self.as_you_type = config['search_as_you_type'] if as_you_type is None else as_you_type
|
||||
self.opt_name = opt_name
|
||||
items = []
|
||||
for item in config[opt_name]:
|
||||
|
107
src/calibre/gui2/viewer/search.py
Normal file
107
src/calibre/gui2/viewer/search.py
Normal file
@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env python2
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
import textwrap
|
||||
from collections import namedtuple
|
||||
|
||||
from PyQt5.Qt import (
|
||||
QCheckBox, QComboBox, QHBoxLayout, QIcon, Qt, QToolButton, QVBoxLayout, QWidget,
|
||||
pyqtSignal
|
||||
)
|
||||
|
||||
from calibre.gui2.viewer.web_view import vprefs
|
||||
from calibre.gui2.widgets2 import HistoryComboBox
|
||||
|
||||
Search = namedtuple('Search', 'text mode case_sensitive backwards')
|
||||
|
||||
|
||||
class SearchInput(QWidget):
|
||||
|
||||
do_search = pyqtSignal(object)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
self.l = l = QVBoxLayout(self)
|
||||
l.setContentsMargins(0, 0, 0, 0)
|
||||
h = QHBoxLayout()
|
||||
h.setContentsMargins(0, 0, 0, 0)
|
||||
l.addLayout(h)
|
||||
|
||||
self.search_box = sb = HistoryComboBox(self)
|
||||
sb.lineEdit().setPlaceholderText(_('Search'))
|
||||
sb.lineEdit().setClearButtonEnabled(True)
|
||||
sb.lineEdit().returnPressed.connect(self.find_next)
|
||||
sb.initialize('viewer-search-box-history')
|
||||
h.addWidget(sb)
|
||||
|
||||
self.next_button = nb = QToolButton(self)
|
||||
h.addWidget(nb)
|
||||
nb.setFocusPolicy(Qt.NoFocus)
|
||||
nb.setIcon(QIcon(I('arrow-down.png')))
|
||||
nb.clicked.connect(self.find_next)
|
||||
nb.setToolTip(_('Find next match'))
|
||||
|
||||
self.prev_button = nb = QToolButton(self)
|
||||
h.addWidget(nb)
|
||||
nb.setFocusPolicy(Qt.NoFocus)
|
||||
nb.setIcon(QIcon(I('arrow-up.png')))
|
||||
nb.clicked.connect(self.find_previous)
|
||||
nb.setToolTip(_('Find previous match'))
|
||||
|
||||
h = QHBoxLayout()
|
||||
h.setContentsMargins(0, 0, 0, 0)
|
||||
l.addLayout(h)
|
||||
self.query_type = qt = QComboBox(self)
|
||||
qt.setFocusPolicy(Qt.NoFocus)
|
||||
qt.addItem(_('Normal'), 'normal')
|
||||
qt.addItem(_('Regex'), 'regex')
|
||||
qt.setToolTip(textwrap.fill(_('Choose the type of search: Normal will search'
|
||||
' for the entered text, Regex will interpret the text as a'
|
||||
' regular expression')))
|
||||
qt.setCurrentIndex(qt.findData(vprefs.get('viewer-search-mode', 'normal') or 'normal'))
|
||||
h.addWidget(qt)
|
||||
|
||||
self.case_sensitive = cs = QCheckBox(_('Case sensitive'), self)
|
||||
cs.setFocusPolicy(Qt.NoFocus)
|
||||
cs.setChecked(bool(vprefs.get('viewer-search-case-sensitive', False)))
|
||||
h.addWidget(cs)
|
||||
|
||||
def search_query(self, backwards=False):
|
||||
text = self.search_box.currentText().strip()
|
||||
if text:
|
||||
return Search(text, self.query_type.currentData() or 'normal', self.case_sensitive.isChecked(), backwards)
|
||||
|
||||
def emit_search(self, backwards=False):
|
||||
vprefs['viewer-search-case-sensitive'] = self.case_sensitive.isChecked()
|
||||
vprefs['viewer-search-mode'] = self.query_type.currentData()
|
||||
sq = self.search_query(backwards)
|
||||
if sq is not None:
|
||||
self.do_search.emit(sq)
|
||||
|
||||
def find_next(self):
|
||||
self.emit_search()
|
||||
|
||||
def find_previous(self):
|
||||
self.emit_search(backwards=True)
|
||||
|
||||
def focus_input(self):
|
||||
self.search_box.setFocus(Qt.OtherFocusReason)
|
||||
le = self.search_box.lineEdit()
|
||||
le.end(False)
|
||||
le.selectAll()
|
||||
|
||||
|
||||
class SearchPanel(QWidget):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
self.l = l = QVBoxLayout(self)
|
||||
self.search_input = si = SearchInput(self)
|
||||
l.addWidget(si)
|
||||
l.addStretch(10)
|
||||
|
||||
def focus_input(self):
|
||||
self.search_input.focus_input()
|
@ -33,6 +33,7 @@ from calibre.gui2.viewer.convert_book import (
|
||||
)
|
||||
from calibre.gui2.viewer.lookup import Lookup
|
||||
from calibre.gui2.viewer.overlay import LoadingOverlay
|
||||
from calibre.gui2.viewer.search import SearchPanel
|
||||
from calibre.gui2.viewer.toc import TOC, TOCSearch, TOCView
|
||||
from calibre.gui2.viewer.toolbars import ActionsToolBar
|
||||
from calibre.gui2.viewer.web_view import (
|
||||
@ -68,6 +69,7 @@ def dock_defs():
|
||||
d(_('Table of Contents'), 'toc', Qt.LeftDockWidgetArea),
|
||||
d(_('Lookup'), 'lookup', Qt.RightDockWidgetArea),
|
||||
d(_('Bookmarks'), 'bookmarks', Qt.RightDockWidgetArea)
|
||||
d(_('Search'), 'search', Qt.LeftDockWidgetArea)
|
||||
d(_('Inspector'), 'inspector', Qt.RightDockWidgetArea, Qt.AllDockWidgetAreas)
|
||||
return ans
|
||||
|
||||
@ -134,6 +136,9 @@ class EbookViewer(MainWindow):
|
||||
w.l.addWidget(self.toc), w.l.addWidget(self.toc_search), w.l.setContentsMargins(0, 0, 0, 0)
|
||||
self.toc_dock.setWidget(w)
|
||||
|
||||
self.search_widget = w = SearchPanel(self)
|
||||
self.search_dock.setWidget(w)
|
||||
|
||||
self.lookup_widget = w = Lookup(self)
|
||||
self.lookup_dock.visibilityChanged.connect(self.lookup_widget.visibility_changed)
|
||||
self.lookup_dock.setWidget(w)
|
||||
@ -151,6 +156,7 @@ class EbookViewer(MainWindow):
|
||||
self.web_view.cfi_changed.connect(self.cfi_changed)
|
||||
self.web_view.reload_book.connect(self.reload_book)
|
||||
self.web_view.toggle_toc.connect(self.toggle_toc)
|
||||
self.web_view.show_search.connect(self.show_search)
|
||||
self.web_view.toggle_bookmarks.connect(self.toggle_bookmarks)
|
||||
self.web_view.toggle_inspector.connect(self.toggle_inspector)
|
||||
self.web_view.toggle_lookup.connect(self.toggle_lookup)
|
||||
@ -237,6 +243,10 @@ class EbookViewer(MainWindow):
|
||||
def toggle_toc(self):
|
||||
self.toc_dock.setVisible(not self.toc_dock.isVisible())
|
||||
|
||||
def show_search(self):
|
||||
self.search_dock.setVisible(True)
|
||||
self.search_widget.focus_input()
|
||||
|
||||
def toggle_bookmarks(self):
|
||||
is_visible = self.bookmarks_dock.isVisible()
|
||||
self.bookmarks_dock.setVisible(not is_visible)
|
||||
|
@ -244,6 +244,7 @@ class ViewerBridge(Bridge):
|
||||
toggle_bookmarks = from_js()
|
||||
toggle_inspector = from_js()
|
||||
toggle_lookup = from_js()
|
||||
show_search = from_js()
|
||||
quit = from_js()
|
||||
update_current_toc_nodes = from_js(object, object)
|
||||
toggle_full_screen = from_js()
|
||||
@ -412,6 +413,7 @@ class WebView(RestartingWebEngineView):
|
||||
cfi_changed = pyqtSignal(object)
|
||||
reload_book = pyqtSignal()
|
||||
toggle_toc = pyqtSignal()
|
||||
show_search = pyqtSignal()
|
||||
toggle_bookmarks = pyqtSignal()
|
||||
toggle_inspector = pyqtSignal()
|
||||
toggle_lookup = pyqtSignal()
|
||||
@ -455,6 +457,7 @@ class WebView(RestartingWebEngineView):
|
||||
self.bridge.set_local_storage.connect(self.set_local_storage)
|
||||
self.bridge.reload_book.connect(self.reload_book)
|
||||
self.bridge.toggle_toc.connect(self.toggle_toc)
|
||||
self.bridge.show_search.connect(self.show_search)
|
||||
self.bridge.toggle_bookmarks.connect(self.toggle_bookmarks)
|
||||
self.bridge.toggle_inspector.connect(self.toggle_inspector)
|
||||
self.bridge.toggle_lookup.connect(self.toggle_lookup)
|
||||
|
@ -529,6 +529,9 @@ class View:
|
||||
|
||||
def show_search(self):
|
||||
self.hide_overlays()
|
||||
if runtime.is_standalone_viewer:
|
||||
ui_operations.show_search()
|
||||
else:
|
||||
self.search_overlay.show()
|
||||
|
||||
def show_content_popup(self):
|
||||
|
@ -339,6 +339,8 @@ if window is window.top:
|
||||
to_python.toggle_inspector()
|
||||
ui_operations.content_file_changed = def(name):
|
||||
to_python.content_file_changed(name)
|
||||
ui_operations.show_search = def():
|
||||
to_python.show_search()
|
||||
ui_operations.reset_interface = def():
|
||||
sd = get_session_data()
|
||||
defaults = session_defaults()
|
||||
|
Loading…
x
Reference in New Issue
Block a user