mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync the main and grid views
This commit is contained in:
parent
b95b0942da
commit
7717fe6d05
@ -6,16 +6,28 @@ from __future__ import (unicode_literals, division, absolute_import,
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
|
import itertools, operator
|
||||||
from time import time
|
from time import time
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from threading import Lock, Event, Thread
|
from threading import Lock, Event, Thread
|
||||||
from Queue import Queue
|
from Queue import Queue
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
from PyQt4.Qt import (
|
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
|
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):
|
class AlternateViews(object):
|
||||||
|
|
||||||
def __init__(self, main_view):
|
def __init__(self, main_view):
|
||||||
@ -23,6 +35,8 @@ class AlternateViews(object):
|
|||||||
self.stack_positions = {None:0}
|
self.stack_positions = {None:0}
|
||||||
self.current_view = self.main_view = main_view
|
self.current_view = self.main_view = main_view
|
||||||
self.stack = None
|
self.stack = None
|
||||||
|
self.break_link = False
|
||||||
|
self.main_connected = False
|
||||||
|
|
||||||
def set_stack(self, stack):
|
def set_stack(self, stack):
|
||||||
self.stack = stack
|
self.stack = stack
|
||||||
@ -34,6 +48,8 @@ class AlternateViews(object):
|
|||||||
self.stack.addWidget(view)
|
self.stack.addWidget(view)
|
||||||
self.stack.setCurrentIndex(0)
|
self.stack.setCurrentIndex(0)
|
||||||
view.setModel(self.main_view._model)
|
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):
|
def show_view(self, key=None):
|
||||||
view = self.views[key]
|
view = self.views[key]
|
||||||
@ -42,13 +58,45 @@ class AlternateViews(object):
|
|||||||
self.stack.setCurrentIndex(self.stack_positions[key])
|
self.stack.setCurrentIndex(self.stack_positions[key])
|
||||||
self.current_view = view
|
self.current_view = view
|
||||||
if view is not self.main_view:
|
if view is not self.main_view:
|
||||||
|
self.main_current_changed(self.main_view.currentIndex())
|
||||||
|
self.main_selection_changed()
|
||||||
view.shown()
|
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):
|
def set_database(self, db, stage=0):
|
||||||
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_database(db, stage=stage)
|
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):
|
class CoverCache(dict):
|
||||||
|
|
||||||
def __init__(self, limit=200):
|
def __init__(self, limit=200):
|
||||||
@ -232,5 +280,19 @@ class GridView(QListView):
|
|||||||
else:
|
else:
|
||||||
self.delegate.cover_cache.clear()
|
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)
|
||||||
|
|
||||||
|
@ -863,7 +863,7 @@ class BooksView(QTableView): # {{{
|
|||||||
self.scrollTo(self.model().index(row, i), self.PositionAtCenter)
|
self.scrollTo(self.model().index(row, i), self.PositionAtCenter)
|
||||||
break
|
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()):
|
if row > -1 and row < self.model().rowCount(QModelIndex()):
|
||||||
h = self.horizontalHeader()
|
h = self.horizontalHeader()
|
||||||
logical_indices = list(range(h.count()))
|
logical_indices = list(range(h.count()))
|
||||||
@ -876,10 +876,14 @@ class BooksView(QTableView): # {{{
|
|||||||
pairs.sort(cmp=lambda x,y:cmp(x[1], y[1]))
|
pairs.sort(cmp=lambda x,y:cmp(x[1], y[1]))
|
||||||
i = pairs[0][0]
|
i = pairs[0][0]
|
||||||
index = self.model().index(row, i)
|
index = self.model().index(row, i)
|
||||||
self.setCurrentIndex(index)
|
if for_sync:
|
||||||
if select:
|
|
||||||
sm = self.selectionModel()
|
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):
|
def keyPressEvent(self, ev):
|
||||||
val = self.horizontalScrollBar().value()
|
val = self.horizontalScrollBar().value()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user