From 6c29207c878ee85b540bdbeaec3120caa5557956 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 2 Mar 2020 10:21:03 +0530 Subject: [PATCH] Rather than remove matches for hidden text, simply mark them as not visible --- src/calibre/gui2/viewer/search.py | 66 +++++++++++-------------------- 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/src/calibre/gui2/viewer/search.py b/src/calibre/gui2/viewer/search.py index c33a1d3646..05d3f92150 100644 --- a/src/calibre/gui2/viewer/search.py +++ b/src/calibre/gui2/viewer/search.py @@ -10,9 +10,9 @@ from threading import Thread import regex from PyQt5.Qt import ( - QCheckBox, QComboBox, QHBoxLayout, QIcon, QLabel, QListWidget, QListWidgetItem, - QStaticText, QStyle, QStyledItemDelegate, Qt, QToolButton, QVBoxLayout, QWidget, - pyqtSignal + QCheckBox, QComboBox, QHBoxLayout, QIcon, QLabel, QListWidget, + QListWidgetItem, QStaticText, QStyle, QStyledItemDelegate, Qt, QToolButton, + QVBoxLayout, QWidget, pyqtSignal ) from calibre.ebooks.conversion.search_replace import REGEX_FLAGS @@ -20,7 +20,6 @@ from calibre.gui2 import warning_dialog from calibre.gui2.progress_indicator import ProgressIndicator from calibre.gui2.viewer.web_view import get_data, get_manifest, vprefs from calibre.gui2.widgets2 import HistoryComboBox -from calibre.utils.monotonic import monotonic from polyglot.builtins import iteritems, unicode_type from polyglot.functools import lru_cache from polyglot.queue import Queue @@ -116,7 +115,7 @@ class SearchFinished(object): class SearchResult(object): - __slots__ = ('search_query', 'before', 'text', 'after', 'q', 'spine_idx', 'index', 'file_name', '_static_text') + __slots__ = ('search_query', 'before', 'text', 'after', 'q', 'spine_idx', 'index', 'file_name', '_static_text', 'is_hidden') def __init__(self, search_query, before, text, after, q, name, spine_idx, index): self.search_query = search_query @@ -125,6 +124,7 @@ class SearchResult(object): self.spine_idx, self.index = spine_idx, index self.file_name = name self._static_text = None + self.is_hidden = False @property def static_text(self): @@ -148,11 +148,11 @@ class SearchResult(object): def for_js(self): return { 'file_name': self.file_name, 'spine_idx': self.spine_idx, 'index': self.index, 'text': self.text, - 'before': self.before, 'after': self.after, 'mode': self.search_query.mode + 'before': self.before, 'after': self.after, 'mode': self.search_query.mode, 'q': self.q } def is_result(self, result_from_js): - return result_from_js['spine_idx'] == self.spine_idx and self.index == result_from_js['index'] and result_from_js['text'] == self.text + return result_from_js['spine_idx'] == self.spine_idx and self.index == result_from_js['index'] and result_from_js['q'] == self.q def __str__(self): from collections import namedtuple @@ -344,8 +344,14 @@ class ResultsDelegate(QStyledItemDelegate): # {{{ c = p.color(group, c) painter.setClipRect(option.rect) painter.setPen(c) + height = result.static_text.size().height() + tl = option.rect.topLeft() + x, y = tl.x(), tl.y() + y += (option.rect.height() - height) // 2 + if result.is_hidden: + x += option.decorationSize.width() + 4 try: - painter.drawStaticText(option.rect.topLeft(), result.static_text) + painter.drawStaticText(x, y, result.static_text) except Exception: import traceback traceback.print_exc() @@ -360,21 +366,23 @@ class Results(QListWidget): # {{{ def __init__(self, parent=None): QListWidget.__init__(self, parent) self.setFocusPolicy(Qt.NoFocus) - self.setStyleSheet('QListWidget::item { padding: 3px; }') self.delegate = ResultsDelegate(self) self.setItemDelegate(self.delegate) self.itemClicked.connect(self.item_activated) + self.blank_icon = QIcon(I('blank.png')) def add_result(self, result): i = QListWidgetItem(' ', self) i.setData(Qt.UserRole, result) + i.setIcon(self.blank_icon) return self.count() def item_activated(self): i = self.currentItem() if i: sr = i.data(Qt.UserRole) - self.show_search_result.emit(sr) + if not sr.is_hidden: + self.show_search_result.emit(sr) def find_next(self, previous): if self.count() < 1: @@ -386,24 +394,14 @@ class Results(QListWidget): # {{{ self.item_activated() def search_result_not_found(self, sr): - remove = None for i in range(self.count()): item = self.item(i) r = item.data(Qt.UserRole) if r.is_result(sr): - remove = i - if remove is not None: - q = sr['spine_idx'] - for i in range(remove + 1, self.count()): - item = self.item(i) - r = item.data(Qt.UserRole) - if r.spine_index != q: - break - r.index -= 1 - self.takeItem(remove) - if self.count(): - self.setCurrentRow(min(remove, self.count()-1)) - self.item_activated() + r.is_hidden = True + item.setToolTip(_('This text is hidden in the book, so cannot be displayed')) + item.setIcon(QIcon(I('dialog_warning.png'))) + break # }}} @@ -520,24 +518,8 @@ class SearchPanel(QWidget): # {{{ def search_result_not_found(self, sr): self.results.search_result_not_found(sr) - if self.results.count(): - now = monotonic() - if self.last_hidden_text_warning is None or self.current_search != self.last_hidden_text_warning[1] or now - self.last_hidden_text_warning[0] > 5: - self.last_hidden_text_warning = now, self.current_search - warning_dialog(self, _('Hidden text'), _( - 'Some search results were for hidden or non-reflowable text, they will be removed.'), show=True) - elif self.last_hidden_text_warning is not None: - self.last_hidden_text_warning = now, self.last_hidden_text_warning[1] - - if not self.results.count() and not self.spinner.is_running: - self.show_no_results_found() def show_no_results_found(self): - has_hidden_text = self.last_hidden_text_warning is not None and self.last_hidden_text_warning[1] == self.current_search - if self.current_search: - if has_hidden_text: - msg = _('No displayable matches were found for:') - else: - msg = _('No matches were found for:') - warning_dialog(self, _('No matches found'), msg + ' {}'.format(self.current_search.text), show=True) + msg = _('No matches were found for:') + warning_dialog(self, _('No matches found'), msg + ' {}'.format(self.current_search.text), show=True) # }}}