From c2b79fe5d93fb1c127ba0ba2351fe6a0118b3c30 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 15 Apr 2009 13:36:37 -0700 Subject: [PATCH] Allow single click fetching of covers in the Edit metadata dialog. Now calibre will automatically try to get the ISBN needed to fetch the cover based on title and author of the book. --- src/calibre/ebooks/metadata/lit.py | 4 +- src/calibre/gui2/__init__.py | 2 + src/calibre/gui2/dialogs/metadata_single.py | 79 +++++++++++++++------ src/calibre/gui2/dialogs/password.ui | 79 +++++++++++---------- 4 files changed, 102 insertions(+), 62 deletions(-) diff --git a/src/calibre/ebooks/metadata/lit.py b/src/calibre/ebooks/metadata/lit.py index 2129af76dd..e45016f303 100644 --- a/src/calibre/ebooks/metadata/lit.py +++ b/src/calibre/ebooks/metadata/lit.py @@ -25,7 +25,7 @@ def get_metadata(stream): for item in litfile.manifest.values(): if item.path in candidates: try: - covers.append((litfile.get_file('/data/'+item.internal), + covers.append((litfile.get_file('/data/'+item.internal), ctype)) except: pass @@ -33,7 +33,7 @@ def get_metadata(stream): covers.sort(cmp=lambda x, y:cmp(len(x[0]), len(y[0])), reverse=True) idx = 0 if len(covers) > 1: - if covers[1][1] == covers[1][0]+'-standard': + if covers[1][1] == covers[0][1]+'-standard': idx = 1 mi.cover_data = ('jpg', covers[idx][0]) return mi diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 1da5bb6851..b3a67d003e 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -69,6 +69,8 @@ def _config(): 'clicked')) c.add_opt('show_donate_button', default=True, help='Show donation button') + c.add_opt('asked_library_thing_password', default=False, + help='Asked library thing password at least once.') return ConfigProxy(c) config = _config() diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py index a9d20905c6..e3d4b5b521 100644 --- a/src/calibre/gui2/dialogs/metadata_single.py +++ b/src/calibre/gui2/dialogs/metadata_single.py @@ -25,24 +25,47 @@ from calibre import islinux from calibre.ebooks.metadata.meta import get_metadata from calibre.utils.config import prefs from calibre.customize.ui import run_plugins_on_import +from calibre.gui2 import config as gui_conf class CoverFetcher(QThread): - def __init__(self, username, password, isbn, timeout): + def __init__(self, username, password, isbn, timeout, title, author): self.username = username self.password = password self.timeout = timeout self.isbn = isbn + self.title = title + self.needs_isbn = False + self.author = author QThread.__init__(self) self.exception = self.traceback = self.cover_data = None def run(self): try: + if not self.isbn: + from calibre.ebooks.metadata.fetch import search + if not self.title: + self.needs_isbn = True + return + au = self.author if self.author else None + key = prefs['isbndb_com_key'] + if not key: + key = None + results = search(title=self.title, author=au, + isbndb_key=key)[0] + results = sorted([x.isbn for x in results if x.isbn], + cmp=lambda x,y:cmp(len(x),len(y)), reverse=True) + if not results: + self.needs_isbn = True + return + self.isbn = results[0] + login(self.username, self.password, force=False) self.cover_data = cover_from_isbn(self.isbn, timeout=self.timeout)[0] except Exception, e: self.exception = e self.traceback = traceback.format_exc() + print self.traceback @@ -64,6 +87,8 @@ class AuthorCompleter(QCompleter): class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): + COVER_FETCH_TIMEOUT = 240 # seconds + def do_reset_cover(self, *args): pix = QPixmap(':/images/book.svg') self.cover.setPixmap(pix) @@ -345,36 +370,39 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): def lt_password_dialog(self): return PasswordDialog(self, 'LibraryThing account', - _('

Enter your username and password for LibraryThing.com.
If you do not have one, you can register for free!.

')) + _('

Enter your username and password for ' + 'LibraryThing.com. This is optional. It will ' + 'make fetching of covers faster and more reliable.
If ' + 'you do not have an account, you can ' + 'register for ' + 'free.

')) def change_password(self): d = self.lt_password_dialog() d.exec_() def fetch_cover(self): - isbn = qstring_to_unicode(self.isbn.text()) - if isbn: - d = self.lt_password_dialog() - if not d.username() or not d.password(): - d.exec_() - if d.result() != PasswordDialog.Accepted: - return - self.fetch_cover_button.setEnabled(False) - self.setCursor(Qt.WaitCursor) - self.cover_fetcher = CoverFetcher(d.username(), d.password(), isbn, - self.timeout) - self.cover_fetcher.start() - self._hangcheck = QTimer(self) - self.connect(self._hangcheck, SIGNAL('timeout()'), self.hangcheck) - self.cf_start_time = time.time() - self.pi.start(_('Downloading cover...')) - self._hangcheck.start(100) - else: - error_dialog(self, _('Cannot fetch cover'), - _('You must specify the ISBN identifier for this book.')).exec_() + isbn = unicode(self.isbn.text()).strip() + d = self.lt_password_dialog() + if not gui_conf['asked_library_thing_password'] and \ + (not d.username() or not d.password()): + d.exec_() + gui_conf['asked_library_thing_password'] = True + self.fetch_cover_button.setEnabled(False) + self.setCursor(Qt.WaitCursor) + title, author = map(unicode, (self.title.text(), self.authors.text())) + self.cover_fetcher = CoverFetcher(d.username(), d.password(), isbn, + self.timeout, title, author) + self.cover_fetcher.start() + self._hangcheck = QTimer(self) + self.connect(self._hangcheck, SIGNAL('timeout()'), self.hangcheck) + self.cf_start_time = time.time() + self.pi.start(_('Downloading cover...')) + self._hangcheck.start(100) def hangcheck(self): - if not (self.cover_fetcher.isFinished() or time.time()-self.cf_start_time > 150): + if not self.cover_fetcher.isFinished() and \ + time.time()-self.cf_start_time < self.COVER_FETCH_TIMEOUT: return self._hangcheck.stop() @@ -385,6 +413,11 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): _('Could not fetch cover.
')+ _('The download timed out.')).exec_() return + if self.cover_fetcher.needs_isbn: + error_dialog(self, _('Cannot fetch cover'), + _('Could not find cover for this book. Try ' + 'specifying the ISBN first.')).exec_() + return if self.cover_fetcher.exception is not None: err = self.cover_fetcher.exception error_dialog(self, _('Cannot fetch cover'), diff --git a/src/calibre/gui2/dialogs/password.ui b/src/calibre/gui2/dialogs/password.ui index 865c065a10..3fc982371e 100644 --- a/src/calibre/gui2/dialogs/password.ui +++ b/src/calibre/gui2/dialogs/password.ui @@ -1,7 +1,8 @@ - + + Dialog - - + + 0 0 @@ -9,66 +10,70 @@ 209 - + Password needed - - :/images/mimetypes/unknown.svg + + + :/images/mimetypes/unknown.svg:/images/mimetypes/unknown.svg - - - - + + + + TextLabel - + + true + + true - - - + + + &Username: - + gui_username - - + + - - - + + + &Password: - + gui_password - - - + + + QLineEdit::Password - - - + + + Qt::Horizontal - - QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - + + + &Show password @@ -76,7 +81,7 @@ - + @@ -85,11 +90,11 @@ Dialog accept() - + 248 254 - + 157 274 @@ -101,11 +106,11 @@ Dialog reject() - + 316 260 - + 286 274