Animated list views, what fun

This commit is contained in:
Kovid Goyal 2011-04-09 11:35:39 -06:00
parent f8d4e6bfa0
commit b231742a01
4 changed files with 56 additions and 14 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -279,7 +279,7 @@ class Worker(Thread): # Get details {{{
class Amazon(Source): class Amazon(Source):
name = 'Amazon Store' name = 'Amazon Web'
description = _('Downloads metadata from Amazon') description = _('Downloads metadata from Amazon')
capabilities = frozenset(['identify', 'cover']) capabilities = frozenset(['identify', 'cover'])

View File

@ -14,7 +14,7 @@ from PyQt4.Qt import (QStyledItemDelegate, QTextDocument, QRectF, QIcon, Qt,
QStyle, QApplication, QDialog, QVBoxLayout, QLabel, QDialogButtonBox, QStyle, QApplication, QDialog, QVBoxLayout, QLabel, QDialogButtonBox,
QStackedWidget, QWidget, QTableView, QGridLayout, QFontInfo, QPalette, QStackedWidget, QWidget, QTableView, QGridLayout, QFontInfo, QPalette,
QTimer, pyqtSignal, QAbstractTableModel, QVariant, QSize, QListView, QTimer, pyqtSignal, QAbstractTableModel, QVariant, QSize, QListView,
QPixmap, QAbstractListModel) QPixmap, QAbstractListModel, QMovie)
from PyQt4.QtWebKit import QWebView from PyQt4.QtWebKit import QWebView
from calibre.customize.ui import metadata_plugins from calibre.customize.ui import metadata_plugins
@ -407,33 +407,66 @@ class CoversModel(QAbstractListModel): # {{{
if current_cover is None: if current_cover is None:
current_cover = QPixmap(I('default_cover.png')) current_cover = QPixmap(I('default_cover.png'))
self.covers = [self.get_item(_('Current cover'), current_cover)] self.blank = QPixmap(I('blank.png')).scaled(150, 200)
for i in range(10):
self.covers.append(self.covers[0]) self.covers = [self.get_item(_('Current cover'), current_cover, False)]
for plugin in metadata_plugins(['cover']):
self.covers.append((plugin.name+'\n'+_('Searching...'),
QVariant(self.blank), None, True))
self.log = log self.log = log
def get_item(self, src, pmap): def get_item(self, src, pmap, waiting=True):
sz = '%dx%d'%(pmap.width(), pmap.height()) sz = '%dx%d'%(pmap.width(), pmap.height())
text = QVariant(src + '\n' + sz) text = QVariant(src + '\n' + sz)
scaled = pmap.scaled(150, 200, Qt.IgnoreAspectRatio, scaled = pmap.scaled(150, 200, Qt.IgnoreAspectRatio,
Qt.SmoothTransformation) Qt.SmoothTransformation)
return (text, QVariant(scaled), pmap) return (text, QVariant(scaled), pmap, waiting)
def rowCount(self, parent=None): def rowCount(self, parent=None):
return len(self.covers) return len(self.covers)
def data(self, index, role): def data(self, index, role):
try: try:
text, pmap = self.covers[index.row()][:2] text, pmap, cover, waiting = self.covers[index.row()]
except: except:
return None return NONE
if role == Qt.DecorationRole: if role == Qt.DecorationRole:
return pmap return pmap
if role == Qt.DisplayRole: if role == Qt.DisplayRole:
return text return text
if role == Qt.UserRole:
return waiting
return NONE return NONE
# }}} # }}}
class CoverDelegate(QStyledItemDelegate):
needs_redraw = pyqtSignal()
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
self.movie = QMovie(I('spinner.gif'))
self.movie.frameChanged.connect(self.frame_changed)
def frame_changed(self, *args):
self.needs_redraw.emit()
def start_movie(self):
self.movie.start()
def stop_movie(self):
self.movie.stop()
def paint(self, painter, option, index):
waiting = index.data(Qt.UserRole).toBool()
if waiting:
pixmap = self.movie.currentPixmap()
prect = pixmap.rect()
prect.moveCenter(option.rect.center())
painter.drawPixmap(prect, pixmap, pixmap.rect())
QStyledItemDelegate.paint(self, painter, option, index)
class CoversView(QListView): # {{{ class CoversView(QListView): # {{{
def __init__(self, log, current_cover, parent=None): def __init__(self, log, current_cover, parent=None):
@ -449,11 +482,20 @@ class CoversView(QListView): # {{{
self.setSelectionMode(self.SingleSelection) self.setSelectionMode(self.SingleSelection)
self.setViewMode(self.IconMode) self.setViewMode(self.IconMode)
self.delegate = CoverDelegate(self)
self.setItemDelegate(self.delegate)
self.delegate.needs_redraw.connect(self.viewport().update,
type=Qt.QueuedConnection)
def select(self, num): def select(self, num):
current = self.model().index(num) current = self.model().index(num)
sm = self.selectionModel() sm = self.selectionModel()
sm.select(current, sm.SelectCurrent) sm.select(current, sm.SelectCurrent)
def start(self):
self.select(0)
self.delegate.start_movie()
# }}} # }}}
class CoverWidget(QWidget): # {{{ class CoverWidget(QWidget): # {{{
@ -476,8 +518,9 @@ class CoverWidget(QWidget): # {{{
self.book, self.current_cover = book, current_cover self.book, self.current_cover = book, current_cover
self.title, self.authors = title, authors self.title, self.authors = title, authors
self.log('\n\nStarting cover download for:', book.title) self.log('\n\nStarting cover download for:', book.title)
self.msg.setText(_('Downloading covers for %s, please wait...')%book.title) self.msg.setText('<p>'+_('Downloading covers for <b>%s</b>, please wait...')%book.title)
self.covers_view.select(0) self.covers_view.start()
# }}} # }}}
class FullFetch(QDialog): # {{{ class FullFetch(QDialog): # {{{
@ -514,7 +557,7 @@ class FullFetch(QDialog): # {{{
self.cover_widget = CoverWidget(self.log, self.current_cover, parent=self) self.cover_widget = CoverWidget(self.log, self.current_cover, parent=self)
self.stack.addWidget(self.cover_widget) self.stack.addWidget(self.cover_widget)
self.resize(850, 500) self.resize(850, 550)
def book_selected(self, book): def book_selected(self, book):
self.next_button.setVisible(False) self.next_button.setVisible(False)

View File

@ -786,8 +786,7 @@ def write_tweaks(raw):
tweaks = read_tweaks() tweaks = read_tweaks()
test_eight_code = tweaks.get('test_eight_code', False) test_eight_code = tweaks.get('test_eight_code', False)
# test_eight_code notes # test_eight_code notes
# Change documentation of bool columns are tristate to indicate that it can be # Change Amazon plugin name to just Amazon
# overridden on a per library basis via Preferences->Custom columns
def migrate(): def migrate():
if hasattr(os, 'geteuid') and os.geteuid() == 0: if hasattr(os, 'geteuid') and os.geteuid() == 0: