Preserve current book when doing searches

When doing searches or switching between virtual libraries in the main
book list, preserve the current book. The currently selected book will
remain visible if it is present in the results of the search or the
selected virtual library. Fixes #1216713 [After selecting books which belongs to same serie, when returning to main window, we are at the top of the list and not at previously selected item](https://bugs.launchpad.net/calibre/+bug/1216713)
This commit is contained in:
Kovid Goyal 2013-09-10 14:13:02 +05:30
parent 778edcbab8
commit c43a3e7969
3 changed files with 68 additions and 1 deletions

View File

@ -226,6 +226,7 @@ class AlternateViews(object):
self.stack = None self.stack = None
self.break_link = False self.break_link = False
self.main_connected = False self.main_connected = False
self.current_book_state = None
def set_stack(self, stack): def set_stack(self, stack):
self.stack = stack self.stack = stack
@ -290,6 +291,15 @@ class AlternateViews(object):
for view in self.views.itervalues(): for view in self.views.itervalues():
if view is not self.main_view: if view is not self.main_view:
view.set_context_menu(menu) 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 {{{ # Rendering of covers {{{
@ -773,4 +783,26 @@ class GridView(QListView):
sm.select(QItemSelection(top, bottom), sm.Select) sm.select(QItemSelection(top, bottom), sm.Select)
else: else:
return QListView.mousePressEvent(self, ev) 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)
# }}} # }}}

View File

@ -120,6 +120,7 @@ class BooksModel(QAbstractTableModel): # {{{
new_bookdisplay_data = pyqtSignal(object) new_bookdisplay_data = pyqtSignal(object)
count_changed_signal = pyqtSignal(int) count_changed_signal = pyqtSignal(int)
searched = pyqtSignal(object) searched = pyqtSignal(object)
search_done = pyqtSignal()
def __init__(self, parent=None, buffer=40): def __init__(self, parent=None, buffer=40):
QAbstractTableModel.__init__(self, parent) 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 # Do not issue search done for the null search. It is used to clear
# the search and count records for restrictions # the search and count records for restrictions
self.searched.emit(True) self.searched.emit(True)
self.search_done.emit()
def sort(self, col, order, reset=True): def sort(self, col, order, reset=True):
if not self.db: if not self.db:

View File

@ -149,6 +149,7 @@ class BooksView(QTableView): # {{{
files_dropped = pyqtSignal(object) files_dropped = pyqtSignal(object)
add_column_signal = pyqtSignal() add_column_signal = pyqtSignal()
is_library_view = True
def viewportEvent(self, event): def viewportEvent(self, event):
if (event.type() == event.ToolTip and not gprefs['book_list_tooltips']): 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) self.scrollTo(self.model().index(row, i), self.PositionAtCenter)
break 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): def set_current_row(self, row=0, select=True, for_sync=False):
if row > -1 and row < self.model().rowCount(QModelIndex()): if row > -1 and row < self.model().rowCount(QModelIndex()):
h = self.horizontalHeader() h = self.horizontalHeader()
@ -929,18 +952,26 @@ class BooksView(QTableView): # {{{
self.select_rows([id_to_select], using_ids=True) self.select_rows([id_to_select], using_ids=True)
def search_proxy(self, txt): 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) self._model.search(txt)
id_to_select = self._model.get_current_highlighted_id() id_to_select = self._model.get_current_highlighted_id()
if id_to_select is not None: if id_to_select is not None:
self.select_rows([id_to_select], using_ids=True) self.select_rows([id_to_select], using_ids=True)
elif self._model.highlight_only: elif self._model.highlight_only:
self.clearSelection() self.clearSelection()
self.setFocus(Qt.OtherFocusReason) if self.isVisible():
self.setFocus(Qt.OtherFocusReason)
def connect_to_search_box(self, sb, search_done): def connect_to_search_box(self, sb, search_done):
sb.search.connect(self.search_proxy) sb.search.connect(self.search_proxy)
self._search_done = search_done self._search_done = search_done
self._model.searched.connect(self.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): def connect_to_book_display(self, bd):
self._model.new_bookdisplay_data.connect(bd) self._model.new_bookdisplay_data.connect(bd)
@ -955,6 +986,8 @@ class BooksView(QTableView): # {{{
class DeviceBooksView(BooksView): # {{{ class DeviceBooksView(BooksView): # {{{
is_library_view = False
def __init__(self, parent): def __init__(self, parent):
BooksView.__init__(self, parent, DeviceBooksModel, BooksView.__init__(self, parent, DeviceBooksModel,
use_edit_metadata_dialog=False) use_edit_metadata_dialog=False)