diff --git a/src/calibre/gui2/library/alternate_views.py b/src/calibre/gui2/library/alternate_views.py index cd8f78202d..d460eec0bb 100644 --- a/src/calibre/gui2/library/alternate_views.py +++ b/src/calibre/gui2/library/alternate_views.py @@ -226,6 +226,7 @@ class AlternateViews(object): self.stack = None self.break_link = False self.main_connected = False + self.current_book_state = None def set_stack(self, stack): self.stack = stack @@ -290,6 +291,15 @@ class AlternateViews(object): for view in self.views.itervalues(): if view is not self.main_view: view.set_context_menu(menu) + + def save_current_book_state(self): + self.current_book_state = self.current_view, self.current_view.current_book_state() + + def restore_current_book_state(self): + if self.current_book_state is not None: + if self.current_book_state[0] is self.current_view: + self.current_view.restore_current_book_state(self.current_book_state[1]) + self.current_book_state = None # }}} # Rendering of covers {{{ @@ -773,4 +783,26 @@ class GridView(QListView): sm.select(QItemSelection(top, bottom), sm.Select) else: return QListView.mousePressEvent(self, ev) + + @property + def current_book(self): + ci = self.currentIndex() + if ci.isValid(): + try: + return self.model().db.data.index_to_id(ci.row()) + except (IndexError, ValueError, KeyError, TypeError, AttributeError): + pass + + def current_book_state(self): + return self.current_book + + def restore_current_book_state(self, state): + book_id = state + try: + row = self.model().db.data.id_to_index(book_id) + except (IndexError, ValueError, KeyError, TypeError, AttributeError): + return + self.set_current_row(row) + self.select_rows((row,)) + self.scrollTo(self.model().index(row, 0), self.PositionAtCenter) # }}} diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index 3d46b0e01e..2db64fd8b3 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -120,6 +120,7 @@ class BooksModel(QAbstractTableModel): # {{{ new_bookdisplay_data = pyqtSignal(object) count_changed_signal = pyqtSignal(int) searched = pyqtSignal(object) + search_done = pyqtSignal() def __init__(self, parent=None, buffer=40): QAbstractTableModel.__init__(self, parent) @@ -392,6 +393,7 @@ class BooksModel(QAbstractTableModel): # {{{ # Do not issue search done for the null search. It is used to clear # the search and count records for restrictions self.searched.emit(True) + self.search_done.emit() def sort(self, col, order, reset=True): if not self.db: diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index 34896c413f..6711da1d9b 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -149,6 +149,7 @@ class BooksView(QTableView): # {{{ files_dropped = pyqtSignal(object) add_column_signal = pyqtSignal() + is_library_view = True def viewportEvent(self, event): if (event.type() == event.ToolTip and not gprefs['book_list_tooltips']): @@ -776,6 +777,28 @@ class BooksView(QTableView): # {{{ self.scrollTo(self.model().index(row, i), self.PositionAtCenter) break + @property + def current_book(self): + ci = self.currentIndex() + if ci.isValid(): + try: + return self.model().db.data.index_to_id(ci.row()) + except (IndexError, ValueError, KeyError, TypeError, AttributeError): + pass + + def current_book_state(self): + return self.current_book, self.horizontalScrollBar().value() + + def restore_current_book_state(self, state): + book_id, hpos = state + try: + row = self.model().db.data.id_to_index(book_id) + except (IndexError, ValueError, KeyError, TypeError, AttributeError): + return + self.set_current_row(row) + self.scroll_to_row(row) + self.horizontalScrollBar().setValue(hpos) + def set_current_row(self, row=0, select=True, for_sync=False): if row > -1 and row < self.model().rowCount(QModelIndex()): h = self.horizontalHeader() @@ -929,18 +952,26 @@ class BooksView(QTableView): # {{{ self.select_rows([id_to_select], using_ids=True) def search_proxy(self, txt): + if self.is_library_view: + # Save the current book before doing the search, after the search + # is completed, this book will become the current book and be + # scrolled to if it is present in the search results + self.alternate_views.save_current_book_state() self._model.search(txt) id_to_select = self._model.get_current_highlighted_id() if id_to_select is not None: self.select_rows([id_to_select], using_ids=True) elif self._model.highlight_only: self.clearSelection() - self.setFocus(Qt.OtherFocusReason) + if self.isVisible(): + self.setFocus(Qt.OtherFocusReason) def connect_to_search_box(self, sb, search_done): sb.search.connect(self.search_proxy) self._search_done = search_done self._model.searched.connect(self.search_done) + if self.is_library_view: + self._model.search_done.connect(self.alternate_views.restore_current_book_state) def connect_to_book_display(self, bd): self._model.new_bookdisplay_data.connect(bd) @@ -955,6 +986,8 @@ class BooksView(QTableView): # {{{ class DeviceBooksView(BooksView): # {{{ + is_library_view = False + def __init__(self, parent): BooksView.__init__(self, parent, DeviceBooksModel, use_edit_metadata_dialog=False)