diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 5f13923ddf..3c05805782 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -855,7 +855,7 @@ class DeviceMixin(object): # {{{ Force the library view to refresh, taking into consideration new device books information ''' - with self.library_view.preserve_selected_books: + with self.library_view.preserve_state(): self.book_on_device(None, reset=True) if reset_only: return @@ -1320,7 +1320,7 @@ class DeviceMixin(object): # {{{ # If it does not, then do it here. if not self.set_books_in_library(self.booklists(), reset=True, add_as_step_to_job=job): self.upload_booklists(job) - with self.library_view.preserve_selected_books: + with self.library_view.preserve_state(): self.book_on_device(None, reset=True) self.refresh_ondevice() diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index 5a62b76c6b..f0f7a33c3c 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -40,7 +40,42 @@ class PreserveSelection(object): # {{{ def __exit__(self, *args): current = self.view.get_selected_ids() if not current: - self.view.select_rows(self.selected_ids, using_ids=True) + self.view.select_rows(self.selected_ids, using_ids=True, + change_current=False, scroll=False) +# }}} + +class PreserveViewState(object): # {{{ + + ''' + Save the set of selected books at enter time. If at exit time there are no + selected books, restore the previous selection, the previous current index + and dont affect the scroll position. + ''' + + def __init__(self, view, preserve_hpos=True, preserve_vpos=True): + self.view = view + self.selected_ids = set() + self.current_id = None + self.preserve_hpos = preserve_hpos + self.preserve_vpos = preserve_vpos + + def __enter__(self): + self.selected_ids = self.view.get_selected_ids() + self.current_id = self.view.current_id + self.vscroll = self.verticalScrollBar().value() + self.hscroll = self.horizontalScrollBar().value() + + def __exit__(self, *args): + current = self.view.get_selected_ids() + if not current and self.selected_ids: + if self.current_id is not None: + self.view.current_id = self.current_id + self.view.select_rows(self.selected_ids, using_ids=True, + scroll=False, change_current=self.current_id is None) + if self.preserve_vpos: + self.verticalScrollBar().setValue(self.vscroll) + if self.preserve_hpos: + self.horizontalScrollBar().setValue(self.hscroll) # }}} class BooksView(QTableView): # {{{ @@ -105,6 +140,7 @@ class BooksView(QTableView): # {{{ self.setSortingEnabled(True) self.selectionModel().currentRowChanged.connect(self._model.current_changed) self.preserve_selected_books = PreserveSelection(self) + self.preserve_state = partial(PreserveViewState, self) # {{{ Column Header setup self.can_add_columns = True @@ -788,6 +824,23 @@ class BooksView(QTableView): # {{{ ans.append(i) return ans + @dynamic_property + def current_id(self): + def fget(self): + try: + return self.model().id(self.currentIndex()) + except: + pass + return None + def fset(self, val): + if val is None: return + m = self.model() + for row in xrange(m.rowCount(QModelIndex())): + if m.id(row) == val: + self.set_current_row(row, select=False) + break + return property(fget=fget, fset=fset) + def close(self): self._model.close()