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.

This commit is contained in:
Kovid Goyal 2009-04-15 13:36:37 -07:00
parent 332dbf4444
commit c2b79fe5d9
4 changed files with 102 additions and 62 deletions

View File

@ -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

View File

@ -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()

View File

@ -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',
_('<p>Enter your username and password for <b>LibraryThing.com</b>. <br/>If you do not have one, you can <a href=\'http://www.librarything.com\'>register</a> for free!.</p>'))
_('<p>Enter your username and password for '
'<b>LibraryThing.com</b>. This is <b>optional</b>. It will '
'make fetching of covers faster and more reliable.<br/>If '
'you do not have an account, you can '
'<a href=\'http://www.librarything.com\'>register</a> for '
'free.</p>'))
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):
_('<b>Could not fetch cover.</b><br/>')+
_('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'),

View File

@ -1,7 +1,8 @@
<ui version="4.0" >
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog" >
<property name="geometry" >
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
@ -9,66 +10,70 @@
<height>209</height>
</rect>
</property>
<property name="windowTitle" >
<property name="windowTitle">
<string>Password needed</string>
</property>
<property name="windowIcon" >
<iconset resource="../images.qrc" >:/images/mimetypes/unknown.svg</iconset>
<property name="windowIcon">
<iconset resource="../images.qrc">
<normaloff>:/images/mimetypes/unknown.svg</normaloff>:/images/mimetypes/unknown.svg</iconset>
</property>
<layout class="QGridLayout" >
<item row="0" column="1" >
<widget class="QLabel" name="msg" >
<property name="text" >
<layout class="QGridLayout">
<item row="0" column="1">
<widget class="QLabel" name="msg">
<property name="text">
<string>TextLabel</string>
</property>
<property name="openExternalLinks" >
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;Username:</string>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>gui_username</cstring>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="QLineEdit" name="gui_username" />
<item row="1" column="1">
<widget class="QLineEdit" name="gui_username"/>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&amp;Password:</string>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>gui_password</cstring>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="QLineEdit" name="gui_password" >
<property name="echoMode" >
<item row="2" column="1">
<widget class="QLineEdit" name="gui_password">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="4" column="1" >
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<item row="4" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="3" column="1" >
<widget class="QCheckBox" name="show_password" >
<property name="text" >
<item row="3" column="1">
<widget class="QCheckBox" name="show_password">
<property name="text">
<string>&amp;Show password</string>
</property>
</widget>
@ -76,7 +81,7 @@
</layout>
</widget>
<resources>
<include location="../images.qrc" />
<include location="../images.qrc"/>
</resources>
<connections>
<connection>
@ -85,11 +90,11 @@
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
@ -101,11 +106,11 @@
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>