From b231742a012a1b5a1e9ba30b4564a482b2d85018 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 9 Apr 2011 11:35:39 -0600 Subject: [PATCH] Animated list views, what fun --- resources/images/spinner.gif | Bin 0 -> 10848 bytes src/calibre/ebooks/metadata/sources/amazon.py | 2 +- src/calibre/gui2/metadata/single_download.py | 65 +++++++++++++++--- src/calibre/utils/config.py | 3 +- 4 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 resources/images/spinner.gif diff --git a/resources/images/spinner.gif b/resources/images/spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..5e864f2e37d51e2b45731822225161780027ea2e GIT binary patch literal 10848 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 literal 0 HcmV?d00001 diff --git a/src/calibre/ebooks/metadata/sources/amazon.py b/src/calibre/ebooks/metadata/sources/amazon.py index b070132de9..4722873f77 100644 --- a/src/calibre/ebooks/metadata/sources/amazon.py +++ b/src/calibre/ebooks/metadata/sources/amazon.py @@ -279,7 +279,7 @@ class Worker(Thread): # Get details {{{ class Amazon(Source): - name = 'Amazon Store' + name = 'Amazon Web' description = _('Downloads metadata from Amazon') capabilities = frozenset(['identify', 'cover']) diff --git a/src/calibre/gui2/metadata/single_download.py b/src/calibre/gui2/metadata/single_download.py index b6bd38a828..2c9b234fba 100644 --- a/src/calibre/gui2/metadata/single_download.py +++ b/src/calibre/gui2/metadata/single_download.py @@ -14,7 +14,7 @@ from PyQt4.Qt import (QStyledItemDelegate, QTextDocument, QRectF, QIcon, Qt, QStyle, QApplication, QDialog, QVBoxLayout, QLabel, QDialogButtonBox, QStackedWidget, QWidget, QTableView, QGridLayout, QFontInfo, QPalette, QTimer, pyqtSignal, QAbstractTableModel, QVariant, QSize, QListView, - QPixmap, QAbstractListModel) + QPixmap, QAbstractListModel, QMovie) from PyQt4.QtWebKit import QWebView from calibre.customize.ui import metadata_plugins @@ -407,33 +407,66 @@ class CoversModel(QAbstractListModel): # {{{ if current_cover is None: current_cover = QPixmap(I('default_cover.png')) - self.covers = [self.get_item(_('Current cover'), current_cover)] - for i in range(10): - self.covers.append(self.covers[0]) + self.blank = QPixmap(I('blank.png')).scaled(150, 200) + + 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 - def get_item(self, src, pmap): + def get_item(self, src, pmap, waiting=True): sz = '%dx%d'%(pmap.width(), pmap.height()) text = QVariant(src + '\n' + sz) scaled = pmap.scaled(150, 200, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) - return (text, QVariant(scaled), pmap) + return (text, QVariant(scaled), pmap, waiting) def rowCount(self, parent=None): return len(self.covers) def data(self, index, role): try: - text, pmap = self.covers[index.row()][:2] + text, pmap, cover, waiting = self.covers[index.row()] except: - return None + return NONE if role == Qt.DecorationRole: return pmap if role == Qt.DisplayRole: return text + if role == Qt.UserRole: + return waiting 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): # {{{ def __init__(self, log, current_cover, parent=None): @@ -449,11 +482,20 @@ class CoversView(QListView): # {{{ self.setSelectionMode(self.SingleSelection) 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): current = self.model().index(num) sm = self.selectionModel() sm.select(current, sm.SelectCurrent) + def start(self): + self.select(0) + self.delegate.start_movie() + # }}} class CoverWidget(QWidget): # {{{ @@ -476,8 +518,9 @@ class CoverWidget(QWidget): # {{{ self.book, self.current_cover = book, current_cover self.title, self.authors = title, authors self.log('\n\nStarting cover download for:', book.title) - self.msg.setText(_('Downloading covers for %s, please wait...')%book.title) - self.covers_view.select(0) + self.msg.setText('

'+_('Downloading covers for %s, please wait...')%book.title) + self.covers_view.start() + # }}} class FullFetch(QDialog): # {{{ @@ -514,7 +557,7 @@ class FullFetch(QDialog): # {{{ self.cover_widget = CoverWidget(self.log, self.current_cover, parent=self) self.stack.addWidget(self.cover_widget) - self.resize(850, 500) + self.resize(850, 550) def book_selected(self, book): self.next_button.setVisible(False) diff --git a/src/calibre/utils/config.py b/src/calibre/utils/config.py index 078971428d..7f2c75a272 100644 --- a/src/calibre/utils/config.py +++ b/src/calibre/utils/config.py @@ -786,8 +786,7 @@ def write_tweaks(raw): tweaks = read_tweaks() test_eight_code = tweaks.get('test_eight_code', False) # test_eight_code notes -# Change documentation of bool columns are tristate to indicate that it can be -# overridden on a per library basis via Preferences->Custom columns +# Change Amazon plugin name to just Amazon def migrate(): if hasattr(os, 'geteuid') and os.geteuid() == 0: