Start work on search panel

This commit is contained in:
Kovid Goyal 2020-01-18 19:15:27 +05:30
parent 90eb2c43f0
commit 8db373d3b5
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 128 additions and 3 deletions

View File

@ -140,8 +140,8 @@ class SearchBox2(QComboBox): # {{{
icon = QIcon(I(icon)) icon = QIcon(I(icon))
return self.lineEdit().addAction(icon, position) return self.lineEdit().addAction(icon, position)
def initialize(self, opt_name, colorize=False, help_text=_('Search')): def initialize(self, opt_name, colorize=False, help_text=_('Search'), as_you_type=None):
self.as_you_type = config['search_as_you_type'] self.as_you_type = config['search_as_you_type'] if as_you_type is None else as_you_type
self.opt_name = opt_name self.opt_name = opt_name
items = [] items = []
for item in config[opt_name]: for item in config[opt_name]:

View 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()

View File

@ -33,6 +33,7 @@ from calibre.gui2.viewer.convert_book import (
) )
from calibre.gui2.viewer.lookup import Lookup from calibre.gui2.viewer.lookup import Lookup
from calibre.gui2.viewer.overlay import LoadingOverlay 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.toc import TOC, TOCSearch, TOCView
from calibre.gui2.viewer.toolbars import ActionsToolBar from calibre.gui2.viewer.toolbars import ActionsToolBar
from calibre.gui2.viewer.web_view import ( from calibre.gui2.viewer.web_view import (
@ -68,6 +69,7 @@ def dock_defs():
d(_('Table of Contents'), 'toc', Qt.LeftDockWidgetArea), d(_('Table of Contents'), 'toc', Qt.LeftDockWidgetArea),
d(_('Lookup'), 'lookup', Qt.RightDockWidgetArea), d(_('Lookup'), 'lookup', Qt.RightDockWidgetArea),
d(_('Bookmarks'), 'bookmarks', Qt.RightDockWidgetArea) d(_('Bookmarks'), 'bookmarks', Qt.RightDockWidgetArea)
d(_('Search'), 'search', Qt.LeftDockWidgetArea)
d(_('Inspector'), 'inspector', Qt.RightDockWidgetArea, Qt.AllDockWidgetAreas) d(_('Inspector'), 'inspector', Qt.RightDockWidgetArea, Qt.AllDockWidgetAreas)
return ans 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) w.l.addWidget(self.toc), w.l.addWidget(self.toc_search), w.l.setContentsMargins(0, 0, 0, 0)
self.toc_dock.setWidget(w) self.toc_dock.setWidget(w)
self.search_widget = w = SearchPanel(self)
self.search_dock.setWidget(w)
self.lookup_widget = w = Lookup(self) self.lookup_widget = w = Lookup(self)
self.lookup_dock.visibilityChanged.connect(self.lookup_widget.visibility_changed) self.lookup_dock.visibilityChanged.connect(self.lookup_widget.visibility_changed)
self.lookup_dock.setWidget(w) self.lookup_dock.setWidget(w)
@ -151,6 +156,7 @@ class EbookViewer(MainWindow):
self.web_view.cfi_changed.connect(self.cfi_changed) self.web_view.cfi_changed.connect(self.cfi_changed)
self.web_view.reload_book.connect(self.reload_book) self.web_view.reload_book.connect(self.reload_book)
self.web_view.toggle_toc.connect(self.toggle_toc) 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_bookmarks.connect(self.toggle_bookmarks)
self.web_view.toggle_inspector.connect(self.toggle_inspector) self.web_view.toggle_inspector.connect(self.toggle_inspector)
self.web_view.toggle_lookup.connect(self.toggle_lookup) self.web_view.toggle_lookup.connect(self.toggle_lookup)
@ -237,6 +243,10 @@ class EbookViewer(MainWindow):
def toggle_toc(self): def toggle_toc(self):
self.toc_dock.setVisible(not self.toc_dock.isVisible()) 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): def toggle_bookmarks(self):
is_visible = self.bookmarks_dock.isVisible() is_visible = self.bookmarks_dock.isVisible()
self.bookmarks_dock.setVisible(not is_visible) self.bookmarks_dock.setVisible(not is_visible)

View File

@ -244,6 +244,7 @@ class ViewerBridge(Bridge):
toggle_bookmarks = from_js() toggle_bookmarks = from_js()
toggle_inspector = from_js() toggle_inspector = from_js()
toggle_lookup = from_js() toggle_lookup = from_js()
show_search = from_js()
quit = from_js() quit = from_js()
update_current_toc_nodes = from_js(object, object) update_current_toc_nodes = from_js(object, object)
toggle_full_screen = from_js() toggle_full_screen = from_js()
@ -412,6 +413,7 @@ class WebView(RestartingWebEngineView):
cfi_changed = pyqtSignal(object) cfi_changed = pyqtSignal(object)
reload_book = pyqtSignal() reload_book = pyqtSignal()
toggle_toc = pyqtSignal() toggle_toc = pyqtSignal()
show_search = pyqtSignal()
toggle_bookmarks = pyqtSignal() toggle_bookmarks = pyqtSignal()
toggle_inspector = pyqtSignal() toggle_inspector = pyqtSignal()
toggle_lookup = pyqtSignal() toggle_lookup = pyqtSignal()
@ -455,6 +457,7 @@ class WebView(RestartingWebEngineView):
self.bridge.set_local_storage.connect(self.set_local_storage) self.bridge.set_local_storage.connect(self.set_local_storage)
self.bridge.reload_book.connect(self.reload_book) self.bridge.reload_book.connect(self.reload_book)
self.bridge.toggle_toc.connect(self.toggle_toc) 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_bookmarks.connect(self.toggle_bookmarks)
self.bridge.toggle_inspector.connect(self.toggle_inspector) self.bridge.toggle_inspector.connect(self.toggle_inspector)
self.bridge.toggle_lookup.connect(self.toggle_lookup) self.bridge.toggle_lookup.connect(self.toggle_lookup)

View File

@ -529,7 +529,10 @@ class View:
def show_search(self): def show_search(self):
self.hide_overlays() self.hide_overlays()
self.search_overlay.show() if runtime.is_standalone_viewer:
ui_operations.show_search()
else:
self.search_overlay.show()
def show_content_popup(self): def show_content_popup(self):
self.hide_overlays() self.hide_overlays()

View File

@ -339,6 +339,8 @@ if window is window.top:
to_python.toggle_inspector() to_python.toggle_inspector()
ui_operations.content_file_changed = def(name): ui_operations.content_file_changed = def(name):
to_python.content_file_changed(name) to_python.content_file_changed(name)
ui_operations.show_search = def():
to_python.show_search()
ui_operations.reset_interface = def(): ui_operations.reset_interface = def():
sd = get_session_data() sd = get_session_data()
defaults = session_defaults() defaults = session_defaults()