Allow clicking on the spinner to abort a search

This commit is contained in:
Kovid Goyal 2022-06-15 15:46:57 +05:30
parent 6e86eb53f3
commit 7d8fe94078
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -6,6 +6,7 @@
import math import math
import os import os
import re import re
import time
import traceback import traceback
from contextlib import suppress from contextlib import suppress
from functools import partial from functools import partial
@ -21,7 +22,7 @@ from threading import Event, Thread
from calibre import fit_image, prepare_string_for_xml from calibre import fit_image, prepare_string_for_xml
from calibre.db import FTSQueryError from calibre.db import FTSQueryError
from calibre.ebooks.metadata import authors_to_string, fmt_sidx from calibre.ebooks.metadata import authors_to_string, fmt_sidx
from calibre.gui2 import config, error_dialog, gprefs, safe_open_url from calibre.gui2 import config, error_dialog, gprefs, question_dialog, safe_open_url
from calibre.gui2.fts.utils import get_db from calibre.gui2.fts.utils import get_db
from calibre.gui2.library.annotations import BusyCursor from calibre.gui2.library.annotations import BusyCursor
from calibre.gui2.progress_indicator import ProgressIndicator from calibre.gui2.progress_indicator import ProgressIndicator
@ -173,6 +174,11 @@ class ResultsModel(QAbstractItemModel):
self.endResetModel() self.endResetModel()
self.search_complete.emit() self.search_complete.emit()
def abort_search(self):
self.current_thread_abort.set()
self.signal_search_complete(self.current_query_id)
self.current_search_key = None # so that re-doing the search works
def search(self, fts_engine_query, use_stemming=True, restrict_to_book_ids=None): def search(self, fts_engine_query, use_stemming=True, restrict_to_book_ids=None):
db = get_db() db = get_db()
failure = [] failure = []
@ -394,6 +400,13 @@ class ResultsView(QTreeView):
class Spinner(ProgressIndicator): class Spinner(ProgressIndicator):
last_mouse_press_at = 0
clicked = pyqtSignal(object)
def __init__(self, *a):
super().__init__(*a)
self.setCursor(Qt.CursorShape.PointingHandCursor)
def sizeHint(self): def sizeHint(self):
return QSize(8, 8) return QSize(8, 8)
@ -401,11 +414,28 @@ class Spinner(ProgressIndicator):
if self.isAnimated(): if self.isAnimated():
super().paintEvent(ev) super().paintEvent(ev)
def mousePressEvent(self, ev):
if ev.button() == Qt.MouseButton.LeftButton:
self.last_mouse_press_at = time.monotonic()
ev.accept()
super().mousePressEvent(ev)
def mouseReleaseEvent(self, ev):
if ev.button() == Qt.MouseButton.LeftButton:
dt = time.monotonic() - self.last_mouse_press_at
self.last_mouse_press_at = 0
if dt < 0.5:
self.clicked.emit(ev)
ev.accept()
return
super().mouseReleaseEvent(ev)
class SearchInputPanel(QWidget): class SearchInputPanel(QWidget):
search_signal = pyqtSignal(object) search_signal = pyqtSignal(object)
clear_search = pyqtSignal() clear_search = pyqtSignal()
request_stop_search = pyqtSignal()
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
@ -443,6 +473,7 @@ class SearchInputPanel(QWidget):
self.v2 = v2 = QVBoxLayout() self.v2 = v2 = QVBoxLayout()
v2.addWidget(sb) v2.addWidget(sb)
self.pi = pi = Spinner(self) self.pi = pi = Spinner(self)
pi.clicked.connect(self.request_stop_search)
v2.addWidget(pi) v2.addWidget(pi)
self.layout().addLayout(v2) self.layout().addLayout(v2)
@ -684,6 +715,7 @@ class ResultsPanel(QWidget):
s.addWidget(lp) s.addWidget(lp)
l = lp.layout() l = lp.layout()
self.sip = sip = SearchInputPanel(parent=self) self.sip = sip = SearchInputPanel(parent=self)
sip.request_stop_search.connect(self.request_stop_search)
l.addWidget(sip) l.addWidget(sip)
self.results_view = rv = ResultsView(parent=self) self.results_view = rv = ResultsView(parent=self)
l.addWidget(rv) l.addWidget(rv)
@ -700,6 +732,10 @@ class ResultsPanel(QWidget):
rv.result_with_context_found.connect(d.result_with_context_found) rv.result_with_context_found.connect(d.result_with_context_found)
s.addWidget(d) s.addWidget(d)
def request_stop_search(self):
if question_dialog(self, _('Are you sure?'), _('Abort the current search?')):
self.results_view.m.abort_search()
def specialize_button_box(self, bb): def specialize_button_box(self, bb):
bb.clear() bb.clear()
bb.addButton(QDialogButtonBox.StandardButton.Close) bb.addButton(QDialogButtonBox.StandardButton.Close)