Sync the main and grid views

This commit is contained in:
Kovid Goyal 2013-08-01 21:27:53 +05:30
parent b95b0942da
commit 7717fe6d05
2 changed files with 71 additions and 5 deletions

View File

@ -6,16 +6,28 @@ from __future__ import (unicode_literals, division, absolute_import,
__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
import itertools, operator
from time import time
from collections import OrderedDict
from threading import Lock, Event, Thread
from Queue import Queue
from functools import wraps
from PyQt4.Qt import (
QListView, QSize, QStyledItemDelegate, QModelIndex, Qt, QImage, pyqtSignal, QPalette, QColor)
QListView, QSize, QStyledItemDelegate, QModelIndex, Qt, QImage, pyqtSignal,
QPalette, QColor, QItemSelection)
from calibre import fit_image
def sync(func):
@wraps(func)
def ans(self, *args, **kwargs):
if self.break_link or self.current_view is self.main_view:
return
with self:
return func(self, *args, **kwargs)
return ans
class AlternateViews(object):
def __init__(self, main_view):
@ -23,6 +35,8 @@ class AlternateViews(object):
self.stack_positions = {None:0}
self.current_view = self.main_view = main_view
self.stack = None
self.break_link = False
self.main_connected = False
def set_stack(self, stack):
self.stack = stack
@ -34,6 +48,8 @@ class AlternateViews(object):
self.stack.addWidget(view)
self.stack.setCurrentIndex(0)
view.setModel(self.main_view._model)
view.selectionModel().currentChanged.connect(self.slave_current_changed)
view.selectionModel().selectionChanged.connect(self.slave_selection_changed)
def show_view(self, key=None):
view = self.views[key]
@ -42,13 +58,45 @@ class AlternateViews(object):
self.stack.setCurrentIndex(self.stack_positions[key])
self.current_view = view
if view is not self.main_view:
self.main_current_changed(self.main_view.currentIndex())
self.main_selection_changed()
view.shown()
if not self.main_connected:
self.main_connected = True
self.main_view.selectionModel().currentChanged.connect(self.main_current_changed)
self.main_view.selectionModel().selectionChanged.connect(self.main_selection_changed)
view.setFocus(Qt.OtherFocusReason)
def set_database(self, db, stage=0):
for view in self.views.itervalues():
if view is not self.main_view:
view.set_database(db, stage=stage)
def __enter__(self):
self.break_link = True
def __exit__(self, *args):
self.break_link = False
@sync
def slave_current_changed(self, current, *args):
self.main_view.set_current_row(current.row(), for_sync=True)
@sync
def slave_selection_changed(self, *args):
rows = {r.row() for r in self.current_view.selectionModel().selectedIndexes()}
self.main_view.select_rows(rows, using_ids=False, change_current=False, scroll=False)
@sync
def main_current_changed(self, current, *args):
self.current_view.set_current_row(current.row())
@sync
def main_selection_changed(self, *args):
rows = {r.row() for r in self.main_view.selectionModel().selectedIndexes()}
self.current_view.select_rows(rows)
class CoverCache(dict):
def __init__(self, limit=200):
@ -232,5 +280,19 @@ class GridView(QListView):
else:
self.delegate.cover_cache.clear()
def select_rows(self, rows):
sel = QItemSelection()
sm = self.selectionModel()
m = self.model()
# Create a range based selector for each set of contiguous rows
# as supplying selectors for each individual row causes very poor
# performance if a large number of rows has to be selected.
for k, g in itertools.groupby(enumerate(rows), lambda (i,x):i-x):
group = list(map(operator.itemgetter(1), g))
sel.merge(QItemSelection(m.index(min(group), 0), m.index(max(group), 0)), sm.Select)
sm.select(sel, sm.ClearAndSelect)
def set_current_row(self, row):
sm = self.selectionModel()
sm.setCurrentIndex(self.model().index(row, 0), sm.NoUpdate)

View File

@ -863,7 +863,7 @@ class BooksView(QTableView): # {{{
self.scrollTo(self.model().index(row, i), self.PositionAtCenter)
break
def set_current_row(self, row=0, select=True):
def set_current_row(self, row=0, select=True, for_sync=False):
if row > -1 and row < self.model().rowCount(QModelIndex()):
h = self.horizontalHeader()
logical_indices = list(range(h.count()))
@ -876,10 +876,14 @@ class BooksView(QTableView): # {{{
pairs.sort(cmp=lambda x,y:cmp(x[1], y[1]))
i = pairs[0][0]
index = self.model().index(row, i)
self.setCurrentIndex(index)
if select:
if for_sync:
sm = self.selectionModel()
sm.select(index, sm.ClearAndSelect|sm.Rows)
sm.setCurrentIndex(index, sm.NoUpdate)
else:
self.setCurrentIndex(index)
if select:
sm = self.selectionModel()
sm.select(index, sm.ClearAndSelect|sm.Rows)
def keyPressEvent(self, ev):
val = self.horizontalScrollBar().value()