diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 4ef2954cec..423791751f 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -47,6 +47,7 @@ from polyglot.builtins import iteritems, string_or_bytes del pqc, geometry_for_restore_as_dict NO_URL_FORMATTING = QUrl.UrlFormattingOption.None_ +BOOK_DETAILS_DISPLAY_DEBOUNCE_DELAY = 100 # 100 ms is threshold for human visual response class IconResourceManager: diff --git a/src/calibre/gui2/dialogs/book_info.py b/src/calibre/gui2/dialogs/book_info.py index 221543d289..e35fb71646 100644 --- a/src/calibre/gui2/dialogs/book_info.py +++ b/src/calibre/gui2/dialogs/book_info.py @@ -4,7 +4,6 @@ import textwrap from enum import IntEnum -from functools import partial from qt.core import ( QAction, QApplication, QBrush, QCheckBox, QDialog, QDialogButtonBox, QGridLayout, @@ -16,6 +15,7 @@ from qt.core import ( from calibre import fit_image from calibre.db.constants import RESOURCE_URL_SCHEME from calibre.gui2 import NO_URL_FORMATTING, gprefs +from calibre.gui2 import BOOK_DETAILS_DISPLAY_DEBOUNCE_DELAY from calibre.gui2.book_details import ( create_open_cover_with_menu, resolved_css, details_context_menu_event, render_html, set_html, ) @@ -24,8 +24,6 @@ from calibre.gui2.widgets import CoverView from calibre.gui2.widgets2 import Dialog, HTMLDisplay from calibre.startup import connect_lambda -BOOK_DETAILS_DISPLAY_DELAY = 250 # 250ms is arbitrary - class Cover(CoverView): @@ -225,7 +223,10 @@ class BookInfo(QDialog): self.path_to_book = None self.current_row = None self.slave_connected = False - self.slave_debounce_timer = QTimer() + self.slave_debounce_timer = t = QTimer(self) + t.setInterval(BOOK_DETAILS_DISPLAY_DEBOUNCE_DELAY) + t.setSingleShot(True) + t.timeout.connect(self._debounce_refresh) if library_path is not None: self.view = None db = get_gui().library_broker.get_library(library_path) @@ -349,13 +350,11 @@ class BookInfo(QDialog): QTimer.singleShot(1, self.resize_cover) def slave(self, mi): - self.slave_debounce_timer.stop() - t = self.book_display_info_timer = QTimer() - t.setSingleShot(True) - t.timeout.connect(partial(self._timed_slave, mi)) - t.start(BOOK_DETAILS_DISPLAY_DELAY) + self._mi_for_debounce = mi + self.slave_debounce_timer.start() # start() will automatically reset the timer if it was already running - def _timed_slave(self, mi): + def _debounce_refresh(self): + mi, self._mi_for_debounce = self._mi_for_debounce, None self.refresh(mi.row_number, mi) def move(self, delta=1): diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index 881d7655c8..99eb8f8184 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -18,7 +18,9 @@ from qt.core import ( from calibre import force_unicode from calibre.constants import filesystem_encoding, islinux -from calibre.gui2 import FunctionDispatcher, error_dialog, gprefs +from calibre.gui2 import ( + BOOK_DETAILS_DISPLAY_DEBOUNCE_DELAY, FunctionDispatcher, error_dialog, gprefs, +) from calibre.gui2.dialogs.enum_values_edit import EnumValuesEdit from calibre.gui2.gestures import GestureManager from calibre.gui2.library import DEFAULT_SORT @@ -27,9 +29,9 @@ from calibre.gui2.library.alternate_views import ( ) from calibre.gui2.library.delegates import ( CcBoolDelegate, CcCommentsDelegate, CcDateDelegate, CcEnumDelegate, - CcLongTextDelegate, CcMarkdownDelegate, CcNumberDelegate, CcSeriesDelegate, CcTemplateDelegate, - CcTextDelegate, CompleteDelegate, DateDelegate, LanguagesDelegate, PubDateDelegate, - RatingDelegate, SeriesDelegate, TextDelegate, + CcLongTextDelegate, CcMarkdownDelegate, CcNumberDelegate, CcSeriesDelegate, + CcTemplateDelegate, CcTextDelegate, CompleteDelegate, DateDelegate, + LanguagesDelegate, PubDateDelegate, RatingDelegate, SeriesDelegate, TextDelegate, ) from calibre.gui2.library.models import BooksModel, DeviceBooksModel from calibre.gui2.pin_columns import PinTableView @@ -1615,16 +1617,20 @@ class BooksView(QTableView): # {{{ self._model.search_done.connect(self.alternate_views.restore_current_book_state) def connect_to_book_display(self, bd): - self.connect_to_book_display_timer = QTimer() - self._model.new_bookdisplay_data.connect(partial(self._timed_connect_to_book_display, bd)) - - def _timed_connect_to_book_display(self, bd, data): - self.connect_to_book_display_timer.stop() - t = self.connect_to_book_display_timer = QTimer() + self.book_display_callback = bd + self.connect_to_book_display_timer = t = QTimer(self) t.setSingleShot(True) - t.timeout.connect(partial(bd, data)) - from calibre.gui2.dialogs.book_info import BOOK_DETAILS_DISPLAY_DELAY - t.start(BOOK_DETAILS_DISPLAY_DELAY) + t.timeout.connect(self._debounce_book_display) + t.setInterval(BOOK_DETAILS_DISPLAY_DEBOUNCE_DELAY) + self._model.new_bookdisplay_data.connect(self._timed_connect_to_book_display) + + def _timed_connect_to_book_display(self, data): + self._book_display_data = data + self.connect_to_book_display_timer.start() + + def _debounce_book_display(self): + data, self._book_display_data = self._book_display_data, None + self.book_display_callback(data) def search_done(self, ok): self._search_done(self, ok) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 12e1291f16..e1d438f9c0 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -1191,6 +1191,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ def shutdown(self, write_settings=True): self.shutting_down = True + if hasattr(self.library_view, 'connect_to_book_display_timer'): + self.library_view.connect_to_book_display_timer.stop() self.shutdown_started.emit() self.show_shutdown_message() self.server_change_notification_timer.stop()