.*?(
.*?).*?
(.*?)
'
+
+
+
+ conversion_options = {
+ 'comment' : description
+ , 'tags' : category
+ , 'publisher' : publisher
+ , 'language' : language
+ , 'linearize_tables' : True
+ }
+
+
+ feeds = [
+ (u'Reviews' , u'http://rogerebert.suntimes.com/apps/pbcs.dll/section?category=reviews' )
+ ,(u'Commentary' , u'http://rogerebert.suntimes.com/apps/pbcs.dll/section?category=COMMENTARY')
+ ,(u'Great Movies' , u'http://rogerebert.suntimes.com/apps/pbcs.dll/section?category=REVIEWS08')
+ ,(u'People' , u'http://rogerebert.suntimes.com/apps/pbcs.dll/section?category=PEOPLE')
+ ,(u'Oscars' , u'http://rogerebert.suntimes.com/apps/pbcs.dll/section?category=OSCARS')
+ ,(u'Glossary' , u'http://rogerebert.suntimes.com/apps/pbcs.dll/section?category=GLOSSARY')
+
+ ]
+
+ preprocess_regexps = [
+ (re.compile(r'
.*?This is a printer friendly.*?.*?
', re.DOTALL|re.IGNORECASE),
+ lambda m: '')
+ ]
+
+
+
+ def print_version(self, url):
+ return url + '&template=printart'
+
+ def parse_index(self):
+ totalfeeds = []
+ lfeeds = self.get_feeds()
+ for feedobj in lfeeds:
+ feedtitle, feedurl = feedobj
+ self.log('\tFeedurl: ', feedurl)
+ self.report_progress(0, _('Fetching feed')+' %s...'%(feedtitle if feedtitle else feedurl))
+ articles = []
+ page = urllib2.urlopen(feedurl).read()
+
+ if feedtitle == 'Reviews' or feedtitle == 'Great Movies':
+ pattern = self.patternReviews
+ elif feedtitle == 'Commentary':
+ pattern = self.patternCommentary
+ elif feedtitle == 'People':
+ pattern = self.patternPeople
+ elif feedtitle == 'Glossary':
+ pattern = self.patternGlossary
+ elif feedtitle == 'Oscars':
+ pattern = self.patternOscars
+
+
+ regex = re.compile(pattern, re.IGNORECASE|re.DOTALL)
+
+ for match in regex.finditer(page):
+ if feedtitle == 'Reviews' or feedtitle == 'Great Movies':
+ movietitle = match.group(1)
+ thislink = match.group(2)
+ description = match.group(3)
+ elif feedtitle == 'Commentary' or feedtitle == 'People' or feedtitle == 'Glossary' or feedtitle == 'Oscars':
+ thislink = match.group(1)
+ description = match.group(2)
+
+ self.log(thislink)
+
+ for link in BeautifulSoup(thislink, parseOnlyThese=SoupStrainer('a')):
+ thisurl = self.PREFIX + link['href']
+ thislinktext = self.tag_to_string(link)
+
+ if feedtitle == 'Reviews' or feedtitle == 'Great Movies':
+ thistitle = movietitle
+ elif feedtitle == 'Commentary' or feedtitle == 'People' or feedtitle == 'Glossary' or feedtitle == 'Oscars':
+ thistitle = thislinktext
+
+ if thistitle == '':
+ continue
+
+
+ pattern2 = r'AID=\/(.*?)\/'
+ reg2 = re.compile(pattern2, re.IGNORECASE|re.DOTALL)
+ match2 = reg2.search(thisurl)
+ if match2:
+ c = time.strptime(match2.group(1),"%Y%m%d")
+ mydate=strftime("%A, %B %d, %Y", c)
+ else:
+ mydate = strftime("%A, %B %d, %Y")
+ self.log(mydate)
+
+ articles.append({
+ 'title' :thistitle
+ ,'date' :' [' + mydate + ']'
+ ,'url' :thisurl
+ ,'description':description
+ })
+ totalfeeds.append((feedtitle, articles))
+
+ return totalfeeds
diff --git a/resources/recipes/swiatkindle.recipe b/resources/recipes/swiatkindle.recipe
new file mode 100644
index 0000000000..a96b4d3ca6
--- /dev/null
+++ b/resources/recipes/swiatkindle.recipe
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+
+__license__ = 'GPL v3'
+__copyright__ = u'2011, Tomasz Dlugosz '
+'''
+swiatkindle.pl
+'''
+
+import re
+
+class swiatkindle(BasicNewsRecipe):
+ title = u'Swiat Kindle'
+ description = u'Blog o czytniku Amazon Kindle. Wersje, ksi\u0105\u017cki, kupowanie i korzystanie w Polsce'
+ language = 'pl'
+ __author__ = u'Tomasz D\u0142ugosz'
+ oldest_article = 7
+ max_articles_per_feed = 100
+
+ feeds = [(u'\u015awiat Kindle - wpisy', u'http://swiatkindle.pl/feed')]
+
+ remove_tags = [dict(name = 'ul', attrs = {'class' : 'similar-posts'})]
+
+ preprocess_regexps = [(re.compile(u'Czytaj dalej:
'), lambda match: '')]
+
diff --git a/setup/commands.py b/setup/commands.py
index 12fb5fe0af..7e22ff14f3 100644
--- a/setup/commands.py
+++ b/setup/commands.py
@@ -17,7 +17,7 @@ __all__ = [
'manual', 'tag_release',
'pypi_register', 'pypi_upload', 'upload_to_server',
'upload_user_manual', 'upload_to_mobileread', 'upload_demo',
- 'upload_to_sourceforge', 'upload_to_google_code',
+ 'upload_to_sourceforge', 'upload_to_google_code', 'reupload',
'linux32', 'linux64', 'linux', 'linux_freeze',
'osx32_freeze', 'osx', 'rsync', 'push',
'win32_freeze', 'win32', 'win',
@@ -63,13 +63,14 @@ stage4 = Stage4()
publish = Publish()
from setup.upload import UploadUserManual, UploadInstallers, UploadDemo, \
- UploadToServer, UploadToSourceForge, UploadToGoogleCode
+ UploadToServer, UploadToSourceForge, UploadToGoogleCode, ReUpload
upload_user_manual = UploadUserManual()
upload_to_mobileread = UploadInstallers()
upload_demo = UploadDemo()
upload_to_server = UploadToServer()
upload_to_sourceforge = UploadToSourceForge()
upload_to_google_code = UploadToGoogleCode()
+reupload = ReUpload()
from setup.installer import Rsync, Push
rsync = Rsync()
diff --git a/setup/installer/linux/freeze2.py b/setup/installer/linux/freeze2.py
index 4d5d1a63e7..20348fa8b8 100644
--- a/setup/installer/linux/freeze2.py
+++ b/setup/installer/linux/freeze2.py
@@ -24,6 +24,7 @@ binary_includes = [
'/usr/bin/pdftohtml',
'/usr/lib/libwmflite-0.2.so.7',
'/usr/lib/liblcms.so.1',
+ '/usr/lib/liblzma.so.0',
'/usr/lib/libunrar.so',
'/usr/lib/libsqlite3.so.0',
'/usr/lib/libmng.so.1',
diff --git a/setup/upload.py b/setup/upload.py
index 1917e0ab1f..cb363be5d7 100644
--- a/setup/upload.py
+++ b/setup/upload.py
@@ -39,8 +39,22 @@ def installer_description(fname):
return 'OS X dmg'
return 'Unknown file'
+class ReUpload(Command): # {{{
-class UploadToGoogleCode(Command):
+ description = 'Re-uplaod any installers present in dist/'
+
+ sub_commands = ['upload_to_google_code', 'upload_to_sourceforge']
+
+ def pre_sub_commands(self, opts):
+ opts.re_upload = True
+
+ def run(self, opts):
+ for x in installers():
+ if os.path.exists(x):
+ os.remove(x)
+# }}}
+
+class UploadToGoogleCode(Command): # {{{
USERNAME = 'kovidgoyal'
# Password can be gotten by going to
@@ -52,21 +66,49 @@ class UploadToGoogleCode(Command):
UPLOAD_HOST = 'calibre-ebook.googlecode.com'
FILES_LIST = 'http://code.google.com/p/calibre-ebook/downloads/list'
+ def add_options(self, parser):
+ parser.add_option('--re-upload', default=False, action='store_true',
+ help='Re-upload all installers currently in dist/')
+
+ def re_upload(self):
+ fnames = set([os.path.basename(x) for x in installers() if not
+ x.endswith('.tar.gz') and os.path.exists(x)])
+ existing = set(self.old_files.keys()).intersection(fnames)
+ br = self.login_to_gmail()
+ for x in fnames:
+ src = os.path.join('dist', x)
+ if not os.access(src, os.R_OK):
+ continue
+ if x in existing:
+ self.info('Deleting', x)
+ br.open('http://code.google.com/p/calibre-ebook/downloads/delete?name=%s'%x)
+ br.select_form(predicate=lambda y: 'delete.do' in y.action)
+ br.form.find_control(name='delete')
+ br.submit(name='delete')
+ self.upload_one(src)
+
+ def upload_one(self, fname):
+ self.info('Uploading', fname)
+ typ = 'Type-Source' if fname.endswith('.gz') else 'Type-Installer'
+ ext = os.path.splitext(fname)[1][1:]
+ op = 'OpSys-'+{'msi':'Windows','dmg':'OSX','bz2':'Linux','gz':'All'}[ext]
+ desc = installer_description(fname)
+ path = self.upload(os.path.abspath(fname), desc,
+ labels=[typ, op, 'Featured'])
+ self.info('\tUploaded to:', path)
+ return path
+
def run(self, opts):
self.opts = opts
self.password = open(self.PASSWORD_FILE).read().strip()
self.paths = {}
self.old_files = self.get_files_hosted_by_google_code()
+ if opts.re_upload:
+ return self.re_upload()
+
for fname in installers():
- self.info('Uploading', fname)
- typ = 'Type-Source' if fname.endswith('.gz') else 'Type-Installer'
- ext = os.path.splitext(fname)[1][1:]
- op = 'OpSys-'+{'msi':'Windows','dmg':'OSX','bz2':'Linux','gz':'All'}[ext]
- desc = installer_description(fname)
- path = self.upload(os.path.abspath(fname), desc,
- labels=[typ, op, 'Featured'])
- self.info('\tUploaded to:', path)
+ path = self.upload_one(fname)
self.paths[os.path.basename(fname)] = path
self.info('Updating path map')
self.info(repr(self.paths))
@@ -189,11 +231,9 @@ class UploadToGoogleCode(Command):
return self.upload(fname, desc, labels=labels, retry=retry+1)
raise Exception('Failed to upload '+fname)
+# }}}
-
-
-
-class UploadToSourceForge(Command):
+class UploadToSourceForge(Command): # {{{
description = 'Upload release files to sourceforge'
@@ -217,9 +257,10 @@ class UploadToSourceForge(Command):
self.opts = opts
self.upload_installers()
+# }}}
-class UploadInstallers(Command):
- description = 'Upload any installers present in dist/'
+class UploadInstallers(Command): # {{{
+ description = 'Upload any installers present in dist/ to mobileread'
def curl_list_dir(self, url=MOBILEREAD, listonly=1):
import pycurl
c = pycurl.Curl()
@@ -289,17 +330,18 @@ class UploadInstallers(Command):
installers = list(map(installer_name, ('dmg', 'msi', 'tar.bz2')))
installers.append(installer_name('tar.bz2', is64bit=True))
map(self.upload_installer, installers)
+# }}}
-class UploadUserManual(Command):
+class UploadUserManual(Command): # {{{
description = 'Build and upload the User Manual'
sub_commands = ['manual']
def run(self, opts):
check_call(' '.join(['scp', '-r', 'src/calibre/manual/.build/html/*',
'divok:%s'%USER_MANUAL]), shell=True)
+# }}}
-
-class UploadDemo(Command):
+class UploadDemo(Command): # {{{
description = 'Rebuild and upload various demos'
@@ -317,8 +359,9 @@ class UploadDemo(Command):
'zip -j /tmp/html-demo.zip * /tmp/html2lrf.lrf', shell=True)
check_call('scp /tmp/html-demo.zip divok:%s/'%(DOWNLOADS,), shell=True)
+# }}}
-class UploadToServer(Command):
+class UploadToServer(Command): # {{{
description = 'Upload miscellaneous data to calibre server'
@@ -348,6 +391,6 @@ class UploadToServer(Command):
check_call('scp %s/*.sha512 divok:%s/signatures/' % (tdir, DOWNLOADS),
shell=True)
shutil.rmtree(tdir)
-
+# }}}
diff --git a/src/calibre/constants.py b/src/calibre/constants.py
index 9d5d4ada30..0245e27c49 100644
--- a/src/calibre/constants.py
+++ b/src/calibre/constants.py
@@ -2,7 +2,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
__appname__ = 'calibre'
-__version__ = '0.7.45'
+__version__ = '0.7.46'
__author__ = "Kovid Goyal "
import re
diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py
index 6cfe915036..4f3574559e 100644
--- a/src/calibre/customize/builtins.py
+++ b/src/calibre/customize/builtins.py
@@ -573,8 +573,8 @@ from calibre.devices.edge.driver import EDGE
from calibre.devices.teclast.driver import TECLAST_K3, NEWSMY, IPAPYRUS, \
SOVOS, PICO, SUNSTECH_EB700, ARCHOS7O, STASH
from calibre.devices.sne.driver import SNE
-from calibre.devices.misc import PALMPRE, AVANT, SWEEX, PDNOVEL, KOGAN, \
- GEMEI, VELOCITYMICRO, PDNOVEL_KOBO, Q600, LUMIREAD, ALURATEK_COLOR, \
+from calibre.devices.misc import PALMPRE, AVANT, SWEEX, PDNOVEL, \
+ GEMEI, VELOCITYMICRO, PDNOVEL_KOBO, LUMIREAD, ALURATEK_COLOR, \
TREKSTOR, EEEREADER, NEXTBOOK
from calibre.devices.folder_device.driver import FOLDER_DEVICE_FOR_CONFIG
from calibre.devices.kobo.driver import KOBO
@@ -691,8 +691,6 @@ plugins += [
AVANT,
MENTOR,
SWEEX,
- Q600,
- KOGAN,
PDNOVEL,
SPECTRA,
GEMEI,
diff --git a/src/calibre/customize/ui.py b/src/calibre/customize/ui.py
index 5f67e23d92..e9feacc67e 100644
--- a/src/calibre/customize/ui.py
+++ b/src/calibre/customize/ui.py
@@ -121,7 +121,8 @@ def enable_plugin(plugin_or_name):
config['enabled_plugins'] = ep
default_disabled_plugins = set([
- 'Douban Books', 'Douban.com covers', 'Nicebooks', 'Nicebooks covers'
+ 'Douban Books', 'Douban.com covers', 'Nicebooks', 'Nicebooks covers',
+ 'Kent District Library'
])
def is_disabled(plugin):
diff --git a/src/calibre/devices/android/driver.py b/src/calibre/devices/android/driver.py
index 53c73b01a0..6f77a4d96c 100644
--- a/src/calibre/devices/android/driver.py
+++ b/src/calibre/devices/android/driver.py
@@ -63,7 +63,8 @@ class ANDROID(USBMS):
0x0e79 : { 0x1419: [0x0216], 0x1420 : [0x0216], 0x1422 : [0x0216]},
# Huawei
- 0x45e : { 0x00e1 : [0x007], },
+ # Disabled as this USB id is used by various USB flash drives
+ #0x45e : { 0x00e1 : [0x007], },
# T-Mobile
0x0408 : { 0x03ba : [0x0109], },
diff --git a/src/calibre/devices/misc.py b/src/calibre/devices/misc.py
index e549a4a9fd..d74f727a0e 100644
--- a/src/calibre/devices/misc.py
+++ b/src/calibre/devices/misc.py
@@ -54,41 +54,24 @@ class AVANT(USBMS):
class SWEEX(USBMS):
# Identical to the Promedia
name = 'Sweex Device Interface'
- gui_name = 'Sweex'
- description = _('Communicate with the Sweex MM300')
+ gui_name = 'Sweex/Kogan/Q600/Wink'
+ description = _('Communicate with the Sweex/Kogan/Q600/Wink')
author = 'Kovid Goyal'
supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats
- FORMATS = ['epub', 'prc', 'fb2', 'html', 'rtf', 'chm', 'pdf', 'txt']
+ FORMATS = ['epub', 'mobi', 'prc', 'fb2', 'html', 'rtf', 'chm', 'pdf', 'txt']
VENDOR_ID = [0x0525, 0x177f]
PRODUCT_ID = [0xa4a5, 0x300]
- BCD = [0x0319, 0x110]
+ BCD = [0x0319, 0x110, 0x325]
- VENDOR_NAME = 'SWEEX'
- WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = 'EBOOKREADER'
+ VENDOR_NAME = ['SWEEX', 'LINUX']
+ WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['EBOOKREADER', 'FILE-STOR_GADGET']
EBOOK_DIR_MAIN = ''
SUPPORTS_SUB_DIRS = True
-class Q600(SWEEX):
-
- name = 'Digma Q600 Device interface'
- gui_name = 'Q600'
- description = _('Communicate with the Digma Q600')
-
- BCD = [0x325]
- FORMATS = ['epub', 'fb2', 'mobi', 'prc', 'html', 'rtf', 'chm', 'pdf', 'txt']
-
-class KOGAN(SWEEX):
-
- name = 'Kogan Device Interface'
- gui_name = 'Kogan'
- description = _('Communicate with the Kogan')
- VENDOR_NAME = 'LINUX'
- WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = 'FILE-STOR_GADGET'
- EBOOK_DIR_MAIN = 'Kogan eBooks'
class PDNOVEL(USBMS):
name = 'Pandigital Novel device interface'
diff --git a/src/calibre/devices/scanner.py b/src/calibre/devices/scanner.py
index 241d503c14..c63eada0c8 100644
--- a/src/calibre/devices/scanner.py
+++ b/src/calibre/devices/scanner.py
@@ -75,6 +75,9 @@ class WinPNPScanner(object):
return order
def __call__(self, debug=False):
+ #import traceback
+ #traceback.print_stack()
+
if self.scanner is None:
return {}
try:
diff --git a/src/calibre/devices/usbms/driver.py b/src/calibre/devices/usbms/driver.py
index 6f8f17f5c9..ef654ac428 100644
--- a/src/calibre/devices/usbms/driver.py
+++ b/src/calibre/devices/usbms/driver.py
@@ -60,7 +60,9 @@ class USBMS(CLI, Device):
def books(self, oncard=None, end_session=True):
from calibre.ebooks.metadata.meta import path_to_ext
- debug_print ('USBMS: Fetching list of books from device. oncard=', oncard)
+ debug_print ('USBMS: Fetching list of books from device. Device=',
+ self.__class__.__name__,
+ 'oncard=', oncard)
dummy_bl = self.booklist_class(None, None, None)
diff --git a/src/calibre/ebooks/fb2/fb2ml.py b/src/calibre/ebooks/fb2/fb2ml.py
index 6af058da7b..43f93807a1 100644
--- a/src/calibre/ebooks/fb2/fb2ml.py
+++ b/src/calibre/ebooks/fb2/fb2ml.py
@@ -350,6 +350,8 @@ class FB2MLizer(object):
# Number of blank lines above tag
try:
ems = int(round((float(style.marginTop) / style.fontSize) - 1))
+ if ems < 0:
+ ems = 0
except:
ems = 0
@@ -397,7 +399,7 @@ class FB2MLizer(object):
fb2_out += p_txt
tags += p_tag
fb2_out.append('' % self.image_hrefs[page.abshref(elem_tree.attrib['src'])])
- if tag in ('br', 'hr') or ems:
+ if tag in ('br', 'hr') or ems >= 1:
if ems < 1:
multiplier = 1
else:
diff --git a/src/calibre/ebooks/lrf/objects.py b/src/calibre/ebooks/lrf/objects.py
index 9f0dd4211c..a83794b7b5 100644
--- a/src/calibre/ebooks/lrf/objects.py
+++ b/src/calibre/ebooks/lrf/objects.py
@@ -854,7 +854,8 @@ class Text(LRFStream):
if len(self.content) == 0:
current_style = style.copy()
name, val = action[0], LRFObject.tag_to_val(action, self, tag, None)
- if name and current_style[name] != val:
+ if name and (name not in current_style or current_style[name]
+ != val):
# No existing Span
if len(self.content) > 0 and isinstance(self.content[-1], self.__class__.Span):
self.content[-1].attrs[name] = val
diff --git a/src/calibre/ebooks/metadata/amazon.py b/src/calibre/ebooks/metadata/amazon.py
index 98a2ac6d36..c87249ed39 100644
--- a/src/calibre/ebooks/metadata/amazon.py
+++ b/src/calibre/ebooks/metadata/amazon.py
@@ -50,7 +50,7 @@ def to_asin(br, isbn):
else:
asin = isbn
with cache_lock:
- asin_cache[isbn] = ans if ans else False
+ asin_cache[isbn] = asin if asin else False
return asin
@@ -205,7 +205,10 @@ def main(args=sys.argv):
open(cpath, 'wb').write(br.open_novisit(curl).read())
print 'Cover for', title, 'saved to', cpath
+ #import time
+ #st = time.time()
print get_social_metadata(title, None, None, isbn)
+ #print '\n\n', time.time() - st, '\n\n'
return 0
diff --git a/src/calibre/ebooks/metadata/fetch.py b/src/calibre/ebooks/metadata/fetch.py
index 4f246b2b9a..667b4f4d7c 100644
--- a/src/calibre/ebooks/metadata/fetch.py
+++ b/src/calibre/ebooks/metadata/fetch.py
@@ -106,6 +106,9 @@ class MetadataSource(Plugin): # {{{
def join(self):
return self.worker.join()
+ def is_alive(self):
+ return self.worker.is_alive()
+
def is_customizable(self):
return True
@@ -251,7 +254,9 @@ class KentDistrictLibrary(MetadataSource): # {{{
name = 'Kent District Library'
metadata_type = 'social'
- description = _('Downloads series information from ww2.kdl.org')
+ description = _('Downloads series information from ww2.kdl.org. '
+ 'This website cannot handle large numbers of queries, '
+ 'so the plugin is disabled by default.')
def fetch(self):
if not self.title or not self.book_author:
diff --git a/src/calibre/ebooks/metadata/kdl.py b/src/calibre/ebooks/metadata/kdl.py
index 4eca49ad45..b0b961b603 100644
--- a/src/calibre/ebooks/metadata/kdl.py
+++ b/src/calibre/ebooks/metadata/kdl.py
@@ -5,7 +5,9 @@ __license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal '
__docformat__ = 'restructuredtext en'
-import re, urllib, urlparse
+import re, urllib, urlparse, socket
+
+from mechanize import URLError
from calibre.ebooks.metadata.book.base import Metadata
from calibre import browser
@@ -17,7 +19,7 @@ URL = \
_ignore_starts = u'\'"'+u''.join(unichr(x) for x in range(0x2018, 0x201e)+[0x2032, 0x2033])
-def get_series(title, authors):
+def get_series(title, authors, timeout=60):
mi = Metadata(title, authors)
if title and title[0] in _ignore_starts:
title = title[1:]
@@ -39,7 +41,12 @@ def get_series(title, authors):
url = URL.format(author, title)
br = browser()
- raw = br.open(url).read()
+ try:
+ raw = br.open_novisit(url, timeout=timeout).read()
+ except URLError, e:
+ if isinstance(e.reason, socket.timeout):
+ raise Exception('KDL Server busy, try again later')
+ raise
if 'see the full results' not in raw:
return mi
raw = xml_to_unicode(raw)[0]
diff --git a/src/calibre/ebooks/metadata/sources/base.py b/src/calibre/ebooks/metadata/sources/base.py
index e5490ef56e..74e184cc66 100644
--- a/src/calibre/ebooks/metadata/sources/base.py
+++ b/src/calibre/ebooks/metadata/sources/base.py
@@ -85,7 +85,8 @@ class Source(Plugin):
# Metadata API {{{
- def identify(self, log, result_queue, abort, title=None, authors=None, identifiers={}):
+ def identify(self, log, result_queue, abort, title=None, authors=None,
+ identifiers={}, timeout=5):
'''
Identify a book by its title/author/isbn/etc.
@@ -98,6 +99,8 @@ class Source(Plugin):
:param authors: A list of authors of the book, can be None
:param identifiers: A dictionary of other identifiers, most commonly
{'isbn':'1234...'}
+ :param timeout: Timeout in seconds, no network request should hang for
+ longer than timeout.
:return: None if no errors occurred, otherwise a unicode representation
of the error suitable for showing to the user
diff --git a/src/calibre/ebooks/metadata/sources/google.py b/src/calibre/ebooks/metadata/sources/google.py
index c59bbe6dc5..498c7574ea 100644
--- a/src/calibre/ebooks/metadata/sources/google.py
+++ b/src/calibre/ebooks/metadata/sources/google.py
@@ -10,7 +10,6 @@ __docformat__ = 'restructuredtext en'
import time
from urllib import urlencode
from functools import partial
-from threading import Thread
from lxml import etree
@@ -18,6 +17,7 @@ from calibre.ebooks.metadata.sources.base import Source
from calibre.ebooks.metadata.book.base import Metadata
from calibre.ebooks.chardet import xml_to_unicode
from calibre.utils.date import parse_date, utcnow
+from calibre.utils.cleantext import clean_ascii_chars
from calibre import browser, as_unicode
NAMESPACES = {
@@ -41,20 +41,20 @@ subject = XPath('descendant::dc:subject')
description = XPath('descendant::dc:description')
language = XPath('descendant::dc:language')
-def get_details(browser, url):
+def get_details(browser, url, timeout):
try:
- raw = browser.open_novisit(url).read()
+ raw = browser.open_novisit(url, timeout=timeout).read()
except Exception as e:
gc = getattr(e, 'getcode', lambda : -1)
if gc() != 403:
raise
# Google is throttling us, wait a little
- time.sleep(2)
- raw = browser.open_novisit(url).read()
+ time.sleep(1)
+ raw = browser.open_novisit(url, timeout=timeout).read()
return raw
-def to_metadata(browser, log, entry_):
+def to_metadata(browser, log, entry_, timeout):
def get_text(extra, x):
try:
@@ -79,8 +79,9 @@ def to_metadata(browser, log, entry_):
mi = Metadata(title_, authors)
try:
- raw = get_details(browser, id_url)
- feed = etree.fromstring(xml_to_unicode(raw, strip_encoding_pats=True)[0])
+ raw = get_details(browser, id_url, timeout)
+ feed = etree.fromstring(xml_to_unicode(clean_ascii_chars(raw),
+ strip_encoding_pats=True)[0])
extra = entry(feed)[0]
except:
log.exception('Failed to get additional details for', mi.title)
@@ -131,26 +132,19 @@ def to_metadata(browser, log, entry_):
return mi
-class Worker(Thread):
- def __init__(self, log, entries, abort, result_queue):
- self.browser, self.log, self.entries = browser(), log, entries
- self.abort, self.result_queue = abort, result_queue
- Thread.__init__(self)
- self.daemon = True
-
- def run(self):
- for i in self.entries:
- try:
- ans = to_metadata(self.browser, self.log, i)
- if isinstance(ans, Metadata):
- self.result_queue.put(ans)
- except:
- self.log.exception(
- 'Failed to get metadata for identify entry:',
- etree.tostring(i))
- if self.abort.is_set():
- break
+def get_all_details(br, log, entries, abort, result_queue, timeout):
+ for i in entries:
+ try:
+ ans = to_metadata(br, log, i, timeout)
+ if isinstance(ans, Metadata):
+ result_queue.put(ans)
+ except:
+ log.exception(
+ 'Failed to get metadata for identify entry:',
+ etree.tostring(i))
+ if abort.is_set():
+ break
class GoogleBooks(Source):
@@ -192,54 +186,40 @@ class GoogleBooks(Source):
})
- def identify(self, log, result_queue, abort, title=None, authors=None, identifiers={}):
+ def identify(self, log, result_queue, abort, title=None, authors=None,
+ identifiers={}, timeout=5):
query = self.create_query(log, title=title, authors=authors,
identifiers=identifiers)
+ br = browser()
try:
- raw = browser().open_novisit(query).read()
+ raw = br.open_novisit(query, timeout=timeout).read()
except Exception, e:
log.exception('Failed to make identify query: %r'%query)
return as_unicode(e)
try:
parser = etree.XMLParser(recover=True, no_network=True)
- feed = etree.fromstring(xml_to_unicode(raw,
+ feed = etree.fromstring(xml_to_unicode(clean_ascii_chars(raw),
strip_encoding_pats=True)[0], parser=parser)
entries = entry(feed)
except Exception, e:
log.exception('Failed to parse identify results')
return as_unicode(e)
-
- groups = self.split_jobs(entries, 5) # At most 5 threads
- if not groups:
- return None
- workers = [Worker(log, entries, abort, result_queue) for entries in
- groups]
-
- if abort.is_set():
- return None
-
- for worker in workers: worker.start()
-
- has_alive_worker = True
- while has_alive_worker and not abort.is_set():
- time.sleep(0.1)
- has_alive_worker = False
- for worker in workers:
- if worker.is_alive():
- has_alive_worker = True
+ # There is no point running these queries in threads as google
+ # throttles requests returning Forbidden errors
+ get_all_details(br, log, entries, abort, result_queue, timeout)
return None
if __name__ == '__main__':
# To run these test use: calibre-debug -e src/calibre/ebooks/metadata/sources/google.py
from calibre.ebooks.metadata.sources.test import (test_identify_plugin,
- isbn_test)
+ title_test)
test_identify_plugin(GoogleBooks.name,
[
(
{'title': 'Great Expectations', 'authors':['Charles Dickens']},
- [isbn_test('9781607541592')]
+ [title_test('Great Expectations', exact=True)]
),
])
diff --git a/src/calibre/ebooks/metadata/sources/test.py b/src/calibre/ebooks/metadata/sources/test.py
index cd7e7ab6e8..3b41e69d40 100644
--- a/src/calibre/ebooks/metadata/sources/test.py
+++ b/src/calibre/ebooks/metadata/sources/test.py
@@ -7,7 +7,7 @@ __license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal '
__docformat__ = 'restructuredtext en'
-import os, tempfile
+import os, tempfile, time
from Queue import Queue, Empty
from threading import Event
@@ -26,6 +26,17 @@ def isbn_test(isbn):
return test
+def title_test(title, exact=False):
+
+ title = title.lower()
+
+ def test(mi):
+ mt = mi.title.lower()
+ return (exact and mt == title) or \
+ (not exact and title in mt)
+
+ return test
+
def test_identify_plugin(name, tests):
'''
:param name: Plugin name
@@ -48,11 +59,15 @@ def test_identify_plugin(name, tests):
abort = Event()
prints('Log saved to', lf)
+ times = []
for kwargs, test_funcs in tests:
prints('Running test with:', kwargs)
rq = Queue()
args = (log, rq, abort)
+ start_time = time.time()
err = plugin.identify(*args, **kwargs)
+ total_time = time.time() - start_time
+ times.append(total_time)
if err is not None:
prints('identify returned an error for args', args)
prints(err)
@@ -87,6 +102,8 @@ def test_identify_plugin(name, tests):
prints('Log saved to', lf)
raise SystemExit(1)
+ prints('Average time per query', sum(times)/len(times))
+
if os.stat(lf).st_size > 10:
prints('There were some errors, see log', lf)
diff --git a/src/calibre/ebooks/metadata/xisbn.py b/src/calibre/ebooks/metadata/xisbn.py
index 2ee74396c7..aaeb1c6b98 100644
--- a/src/calibre/ebooks/metadata/xisbn.py
+++ b/src/calibre/ebooks/metadata/xisbn.py
@@ -11,6 +11,12 @@ from calibre import browser
class xISBN(object):
+ '''
+ This class is used to find the ISBN numbers of "related" editions of a
+ book, given its ISBN. Useful when querying services for metadata by ISBN,
+ in case they do not have the ISBN for the particular edition.
+ '''
+
QUERY = 'http://xisbn.worldcat.org/webservices/xid/isbn/%s?method=getEditions&format=json&fl=form,year,lang,ed'
def __init__(self):
diff --git a/src/calibre/ebooks/pdf/images.cpp b/src/calibre/ebooks/pdf/images.cpp
index 4cd1ace776..0e7d8b0d70 100644
--- a/src/calibre/ebooks/pdf/images.cpp
+++ b/src/calibre/ebooks/pdf/images.cpp
@@ -301,7 +301,7 @@ void PNGWriter::write_splash_bitmap(SplashBitmap *bitmap) {
void calibre_png_mem_write(png_structp png_ptr, png_bytep data, png_size_t length) {
if (!png_ptr || length < 1) return;
- vector *buf = static_cast< vector* >(png_ptr->io_ptr);
+ vector *buf = static_cast< vector* >(png_get_io_ptr(png_ptr));
buf->reserve(buf->capacity() + length);
do {
buf->push_back(static_cast(*data));
diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py
index 8801777953..8563956b28 100644
--- a/src/calibre/gui2/actions/__init__.py
+++ b/src/calibre/gui2/actions/__init__.py
@@ -27,7 +27,7 @@ class InterfaceAction(QObject):
If two :class:`InterfaceAction` objects have the same name, the one with higher
priority takes precedence.
- Sub-classes should implement the :meth:`genesis`, :meth:`library_moved`,
+ Sub-classes should implement the :meth:`genesis`, :meth:`library_changed`,
:meth:`location_selected` :meth:`shutting_down`
and :meth:`initialization_complete` methods.
diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py
index 49a7a4677a..f99e48eb2b 100644
--- a/src/calibre/gui2/actions/add.py
+++ b/src/calibre/gui2/actions/add.py
@@ -259,6 +259,7 @@ class AddAction(InterfaceAction):
if hasattr(self.gui, 'db_images'):
self.gui.db_images.reset()
self.gui.tags_view.recount()
+
if getattr(self._adder, 'merged_books', False):
books = u'\n'.join([x if isinstance(x, unicode) else
x.decode(preferred_encoding, 'replace') for x in
@@ -266,6 +267,17 @@ class AddAction(InterfaceAction):
info_dialog(self.gui, _('Merged some books'),
_('The following duplicate books were found and incoming book formats were '
'processed and merged into your Calibre database according to your automerge settings:'), det_msg=books, show=True)
+
+ if getattr(self._adder, 'number_of_books_added', 0) > 0 or \
+ getattr(self._adder, 'merged_books', False):
+ # The formats of the current book could have changed if
+ # automerge is enabled
+ current_idx = self.gui.library_view.currentIndex()
+ if current_idx.isValid():
+ self.gui.library_view.model().current_changed(current_idx,
+ current_idx)
+
+
if getattr(self._adder, 'critical', None):
det_msg = []
for name, log in self._adder.critical.items():
diff --git a/src/calibre/gui2/complete.py b/src/calibre/gui2/complete.py
index c56882ac31..c99cd47373 100644
--- a/src/calibre/gui2/complete.py
+++ b/src/calibre/gui2/complete.py
@@ -62,7 +62,7 @@ class MultiCompleteLineEdit(QLineEdit, LineEditECM):
c.setWidget(self)
c.setCompletionMode(QCompleter.PopupCompletion)
c.setCaseSensitivity(Qt.CaseInsensitive)
- c.setModelSorting(QCompleter.CaseInsensitivelySortedModel)
+ c.setModelSorting(QCompleter.UnsortedModel)
c.setCompletionRole(Qt.DisplayRole)
p = c.popup()
p.setMouseTracking(True)
diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py
index cdb254ac78..c1627d7e12 100644
--- a/src/calibre/gui2/dialogs/metadata_bulk.py
+++ b/src/calibre/gui2/dialogs/metadata_bulk.py
@@ -3,7 +3,7 @@ __copyright__ = '2008, Kovid Goyal '
'''Dialog to edit metadata in bulk'''
-import re, os
+import re, os, inspect
from PyQt4.Qt import Qt, QDialog, QGridLayout, QVBoxLayout, QFont, QLabel, \
pyqtSignal, QDialogButtonBox, QInputDialog, QLineEdit, \
@@ -711,10 +711,6 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
val = self.s_r_do_regexp(mi)
val = self.s_r_do_destination(mi, val)
if dfm['is_multiple']:
- if dfm['is_custom']:
- # The standard tags and authors values want to be lists.
- # All custom columns are to be strings
- val = dfm['is_multiple'].join(val)
if dest == 'authors' and len(val) == 0:
error_dialog(self, _('Search/replace invalid'),
_('Authors cannot be set to the empty string. '
@@ -732,8 +728,9 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
if dfm['is_custom']:
extra = self.db.get_custom_extra(id, label=dfm['label'], index_is_id=True)
- self.db.set_custom(id, val, label=dfm['label'], extra=extra,
- commit=False)
+ books_to_refresh = self.db.set_custom(id, val, label=dfm['label'],
+ extra=extra, commit=False,
+ allow_case_change=True)
else:
if dest == 'comments':
setter = self.db.set_comment
@@ -741,10 +738,19 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
setter = self.db.set_title_sort
else:
setter = getattr(self.db, 'set_'+dest)
- if dest in ['title', 'authors']:
- setter(id, val, notify=False)
+
+ args = inspect.getargspec(setter)
+ if args and 'allow_case_change' in args.args:
+ books_to_refresh = setter(id, val, notify=False, commit=False,
+ allow_case_change=True)
else:
setter(id, val, notify=False, commit=False)
+ books_to_refresh = set([])
+ if books_to_refresh:
+ # Must commit here because we are telling the gui that the data is
+ # permanent. Make sure it really is.
+ self.db.commit()
+ self.model.refresh_ids(list(books_to_refresh))
def create_custom_column_editors(self):
w = self.central_widget.widget(1)
diff --git a/src/calibre/gui2/preferences/create_custom_column.py b/src/calibre/gui2/preferences/create_custom_column.py
index 5cd32a4af3..9974de472f 100644
--- a/src/calibre/gui2/preferences/create_custom_column.py
+++ b/src/calibre/gui2/preferences/create_custom_column.py
@@ -153,17 +153,17 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
display_dict = {}
if col_type == 'datetime':
- if self.date_format_box.text().strip():
+ if unicode(self.date_format_box.text()).strip():
display_dict = {'date_format':unicode(self.date_format_box.text()).strip()}
else:
display_dict = {'date_format': None}
elif col_type == 'composite':
- if not self.composite_box.text().strip():
+ if not unicode(self.composite_box.text()).strip():
return self.simple_error('', _('You must enter a template for'
' composite columns'))
display_dict = {'composite_template':unicode(self.composite_box.text()).strip()}
elif col_type == 'enumeration':
- if not self.enum_box.text():
+ if not unicode(self.enum_box.text()).strip():
return self.simple_error('', _('You must enter at least one'
' value for enumeration columns'))
l = [v.strip() for v in unicode(self.enum_box.text()).split(',')]
diff --git a/src/calibre/gui2/tag_view.py b/src/calibre/gui2/tag_view.py
index c2b0e4638b..3af3271921 100644
--- a/src/calibre/gui2/tag_view.py
+++ b/src/calibre/gui2/tag_view.py
@@ -1096,7 +1096,8 @@ class TagsModel(QAbstractItemModel): # {{{
if tag in nodes_seen:
continue
nodes_seen.add(tag)
- ans.append('%s%s:"=%s"'%(prefix, category, tag.name))
+ ans.append('%s%s:"=%s"'%(prefix, category,
+ tag.name.replace(r'"', r'\"')))
return ans
def find_item_node(self, key, txt, start_path):
diff --git a/src/calibre/libunrar.py b/src/calibre/libunrar.py
index 4bfd5c537a..2cebd40a79 100644
--- a/src/calibre/libunrar.py
+++ b/src/calibre/libunrar.py
@@ -13,7 +13,7 @@ from tempfile import NamedTemporaryFile
from StringIO import StringIO
from calibre import iswindows, load_library, CurrentDir
-from calibre.ptempfile import TemporaryDirectory
+from calibre.ptempfile import TemporaryDirectory, PersistentTemporaryFile
_librar_name = 'libunrar'
cdll = ctypes.cdll
@@ -270,15 +270,23 @@ def extract_member(path, match=re.compile(r'\.(jpg|jpeg|gif|png)\s*$', re.I),
return path, open(path, 'rb').read()
def extract_first_alphabetically(path):
+ remove_path = False
if hasattr(path, 'read'):
data = path.read()
- f = NamedTemporaryFile(suffix='.rar')
- f.write(data)
- f.flush()
+ with PersistentTemporaryFile('.rar') as f:
+ f.write(data)
path = f.name
+ remove_path = True
names_ = [x for x in names(path) if os.path.splitext(x)[1][1:].lower() in
('png', 'jpg', 'jpeg', 'gif')]
names_.sort()
- return extract_member(path, name=names_[0], match=None)
+ ans = extract_member(path, name=names_[0], match=None)
+ try:
+ if remove_path:
+ os.remove(path)
+ except:
+ pass
+ return ans
+
diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot
index 929e69ad72..8460943e3c 100644
--- a/src/calibre/translations/calibre.pot
+++ b/src/calibre/translations/calibre.pot
@@ -4,9 +4,9 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: calibre 0.7.45\n"
-"POT-Creation-Date: 2011-02-15 11:37+MST\n"
-"PO-Revision-Date: 2011-02-15 11:37+MST\n"
+"Project-Id-Version: calibre 0.7.46\n"
+"POT-Creation-Date: 2011-02-18 11:38+MST\n"
+"PO-Revision-Date: 2011-02-18 11:38+MST\n"
"Last-Translator: Automatically generated\n"
"Language-Team: LANGUAGE\n"
"MIME-Version: 1.0\n"
@@ -25,7 +25,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:74
#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:77
#: /home/kovid/work/calibre/src/calibre/devices/kobo/books.py:24
-#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:465
+#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:482
#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:70
#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:71
#: /home/kovid/work/calibre/src/calibre/devices/prs500/books.py:267
@@ -69,7 +69,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/rtf.py:91
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/rtf.py:101
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/snb.py:16
-#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/sources/google.py:61
+#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/sources/google.py:75
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/txt.py:18
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/txtz.py:23
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:42
@@ -116,7 +116,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:314
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:308
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:315
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:100
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:101
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:332
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:335
#: /home/kovid/work/calibre/src/calibre/gui2/add.py:160
@@ -138,8 +138,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/email.py:245
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:421
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:440
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:977
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1170
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:972
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1165
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:70
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:185
@@ -147,14 +147,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:197
#: /home/kovid/work/calibre/src/calibre/library/cli.py:215
#: /home/kovid/work/calibre/src/calibre/library/database.py:914
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:437
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:443
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:453
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:1557
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:1660
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:2563
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:2565
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:2696
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:448
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:454
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:464
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:1568
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:1671
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:2574
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:2576
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:2707
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:233
#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:158
#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:161
@@ -212,247 +212,247 @@ msgstr ""
msgid "Preferences"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:17
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:18
msgid "Follow all local links in an HTML file and create a ZIP file containing all linked files. This plugin is run every time you add an HTML file to the library."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:53
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:54
msgid "Character encoding for the input HTML files. Common choices include: cp1252, latin1, iso-8859-1 and utf-8."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:60
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:61
msgid "Create a PMLZ archive containing the PML file and all images in the directory pmlname_img or images. This plugin is run every time you add a PML file to the library."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:90
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:91
msgid "Create a TXTZ archive when a TXT file is imported containing Markdown or Textile references to images. The referenced images as well as the TXT file are added to the archive."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:154
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:166
msgid "Extract cover from comic files"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:183
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:194
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:195
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:206
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:216
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:226
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:237
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:247
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:257
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:267
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:277
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:287
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:297
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:308
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:218
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:228
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:238
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:249
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:259
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:269
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:279
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:289
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:299
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:309
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:320
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:341
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:352
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:362
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:373
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:383
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:394
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:332
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:353
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:364
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:374
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:385
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:395
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:406
msgid "Read metadata from %s files"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:331
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:343
msgid "Read metadata from ebooks in RAR archives"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:405
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:417
msgid "Read metadata from ebooks in ZIP archives"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:418
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:428
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:438
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:460
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:471
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:481
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:430
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:440
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:450
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:472
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:483
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:493
msgid "Set metadata in %s files"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:449
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:492
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:461
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:504
msgid "Set metadata from %s files"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:812
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:824
msgid "Look and Feel"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:814
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:826
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:837
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:848
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:838
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:849
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:860
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:872
msgid "Interface"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:818
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:830
msgid "Adjust the look and feel of the calibre interface to suit your tastes"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:824
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:836
msgid "Behavior"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:830
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:842
msgid "Change the way calibre behaves"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:835
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:847
#: /home/kovid/work/calibre/src/calibre/gui2/library/views.py:217
msgid "Add your own columns"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:841
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:853
msgid "Add/remove your own columns to the calibre book list"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:846
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:858
msgid "Customize the toolbar"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:852
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:864
msgid "Customize the toolbars and context menus, changing which actions are available in each"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:858
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:870
msgid "Customize searching"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:864
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:876
msgid "Customize the way searching for books works in calibre"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:869
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:881
msgid "Input Options"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:871
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:882
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:893
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:883
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:894
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:905
msgid "Conversion"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:875
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:887
msgid "Set conversion options specific to each input format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:880
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:892
msgid "Common Options"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:886
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:898
msgid "Set conversion options common to all formats"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:891
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:903
msgid "Output Options"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:897
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:909
msgid "Set conversion options specific to each output format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:902
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:914
msgid "Adding books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:904
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:916
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:928
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:940
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:952
msgid "Import/Export"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:908
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:920
msgid "Control how calibre reads metadata from files when adding books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:914
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:926
msgid "Saving books to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:920
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:932
msgid "Control how calibre exports files from its database to disk when using Save to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:926
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:938
msgid "Sending books to devices"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:932
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:944
msgid "Control how calibre transfers files to your ebook reader"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:938
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:950
msgid "Metadata plugboards"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:944
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:956
msgid "Change metadata fields before saving/sending"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:949
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:961
msgid "Template Functions"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:951
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:987
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:963
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:999
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1010
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1011
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1022
msgid "Advanced"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:955
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:967
msgid "Create your own template functions"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:960
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:972
msgid "Sharing books by email"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:962
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:974
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:986
msgid "Sharing"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:966
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:978
msgid "Setup sharing of books via email. Can be used for automatic sending of downloaded news to your devices"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:972
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:984
msgid "Sharing over the net"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:978
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:990
msgid "Setup the calibre Content Server which will give you access to your calibre library from anywhere, on any device, over the internet"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:985
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:997
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/plugins.py:267
msgid "Plugins"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:991
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1003
msgid "Add/remove/customize various bits of calibre functionality"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:997
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1009
msgid "Tweaks"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1003
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1015
msgid "Fine tune how calibre behaves in various contexts"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1008
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1020
msgid "Miscellaneous"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1014
+#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1026
msgid "Miscellaneous advanced configuration"
msgstr ""
@@ -605,35 +605,35 @@ msgstr ""
msgid "This profile is intended for the Sanda Bambook."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:34
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:35
msgid "Installed plugins"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:35
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:36
msgid "Mapping for filetype plugins"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:36
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:37
msgid "Local plugin customization"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:37
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:38
msgid "Disabled plugins"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:38
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:39
msgid "Enabled plugins"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:93
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:94
msgid "No valid plugin found in "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:508
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:520
msgid "Initialization of plugin %s failed with traceback:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:541
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:553
msgid ""
" %prog options\n"
"\n"
@@ -641,27 +641,27 @@ msgid ""
" "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:547
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:559
msgid "Add a plugin by specifying the path to the zip file containing it."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:549
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:561
msgid "Remove a custom plugin by name. Has no effect on builtin plugins"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:551
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:563
msgid "Customize plugin. Specify name of plugin and customization string separated by a comma."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:553
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:565
msgid "List all installed plugins"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:555
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:567
msgid "Enable the named plugin"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/customize/ui.py:557
+#: /home/kovid/work/calibre/src/calibre/customize/ui.py:569
msgid "Disable the named plugin"
msgstr ""
@@ -673,11 +673,11 @@ msgstr ""
msgid "Communicate with Android phones."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:73
+#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:74
msgid "Comma separated list of directories to send e-books to on the device. The first one that exists will be used"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:120
+#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:121
msgid "Communicate with S60 phones."
msgstr ""
@@ -706,14 +706,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:380
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:949
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:989
-#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2974
-#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:3014
+#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2971
+#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:3011
msgid "%d of %d"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:387
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:994
-#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:3020
+#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:3017
msgid "finished"
msgstr ""
@@ -738,7 +738,7 @@ msgid ""
"Click 'Show Details' for a list."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2555
+#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2552
#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:100
#: /home/kovid/work/calibre/src/calibre/devices/prs505/sony_cache.py:447
#: /home/kovid/work/calibre/src/calibre/devices/prs505/sony_cache.py:470
@@ -748,20 +748,20 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:262
#: /home/kovid/work/calibre/src/calibre/library/database2.py:255
#: /home/kovid/work/calibre/src/calibre/library/database2.py:268
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:2438
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:150
msgid "News"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2556
+#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2553
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:65
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:634
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:2390
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:2408
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:2401
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:2419
msgid "Catalog"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2878
+#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2875
msgid "Communicate with iTunes."
msgstr ""
@@ -800,7 +800,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:67
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:70
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:73
-#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:213
+#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:226
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:68
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:71
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:74
@@ -820,8 +820,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:285
#: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:299
-#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:326
-#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:361
+#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:343
+#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:378
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:221
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:252
msgid "Adding books to device metadata listing..."
@@ -831,8 +831,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:309
#: /home/kovid/work/calibre/src/calibre/devices/hanvon/driver.py:102
#: /home/kovid/work/calibre/src/calibre/devices/hanvon/driver.py:113
-#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:278
-#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:310
+#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:295
+#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:327
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:258
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:276
msgid "Removing books from device..."
@@ -840,8 +840,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:324
#: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:329
-#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:314
-#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:321
+#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:331
+#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:338
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:283
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:288
msgid "Removing books from device metadata listing..."
@@ -1043,12 +1043,12 @@ msgstr ""
msgid "The Kobo supports only one collection currently: the \"Im_Reading\" list. Create a tag called \"Im_Reading\" "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:445
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:296
+#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:462
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:315
msgid "Not Implemented"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:446
+#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:463
msgid "\".kobo\" files do not exist on the device as books instead, they are rows in the sqlite database. Currently they cannot be exported or viewed."
msgstr ""
@@ -2192,7 +2192,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:60
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:65
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:418
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:982
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:977
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:304
#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:590
msgid "Title"
@@ -2202,7 +2202,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:61
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:423
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:983
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:978
msgid "Author(s)"
msgstr ""
@@ -2223,7 +2223,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:114
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:79
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:380
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1189
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1184
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:188
msgid "Comments"
msgstr ""
@@ -2234,9 +2234,9 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:60
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:73
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:368
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1185
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1180
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:161
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:657
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:691
msgid "Tags"
msgstr ""
@@ -2246,7 +2246,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:60
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:74
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:385
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1194
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1189
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:109
msgid "Series"
msgstr ""
@@ -2256,7 +2256,7 @@ msgid "Language"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:626
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1177
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1172
msgid "Timestamp"
msgstr ""
@@ -2408,6 +2408,7 @@ msgid "Convert comments downloaded from %s to plain text"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:178
+#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/sources/google.py:159
msgid "Downloads metadata from Google Books"
msgstr ""
@@ -2606,7 +2607,11 @@ msgstr ""
msgid "Cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/sources/base.py:14
+#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/sources/amazon.py:16
+msgid "Downloads metadata from Amazon"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/sources/base.py:22
msgid "Metadata source"
msgstr ""
@@ -2731,7 +2736,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/jacket.py:169
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:71
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:655
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:689
msgid "Rating"
msgstr ""
@@ -3228,124 +3233,132 @@ msgstr ""
msgid "Choose Files"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:27
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:29
msgid "Add books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:28
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:30
msgid "Add books to the calibre library/device from files on your computer"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:29
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:31
msgid "A"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:35
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:37
msgid "Add books from a single directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:37
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:39
msgid "Add books from directories, including sub-directories (One book per directory, assumes every ebook file is the same book in a different format)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:41
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:43
msgid "Add books from directories, including sub directories (Multiple books per directory, assumes every ebook file is a different book)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:45
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:47
msgid "Add Empty book. (Book entry with no formats)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:46
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:48
msgid "Shift+Ctrl+E"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:47
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:49
msgid "Add from ISBN"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:175
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:237
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:113
+msgid "Adding"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:114
+msgid "Creating book records from ISBNs"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:194
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:256
msgid "Uploading books to device."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:192
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:211
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:308
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:529
msgid "Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:193
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:212
msgid "EPUB Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:194
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:213
msgid "LRF Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:195
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:214
msgid "HTML Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:196
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:215
msgid "LIT Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:197
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:216
msgid "MOBI Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:198
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:217
msgid "Topaz books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:199
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:218
msgid "Text books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:200
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:219
msgid "PDF Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:201
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:220
msgid "SNB Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:202
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:221
msgid "Comics"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:203
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:222
msgid "Archives"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:208
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:227
msgid "Supported books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:247
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:266
msgid "Merged some books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:248
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:267
msgid "The following duplicate books were found and incoming book formats were processed and merged into your Calibre database according to your automerge settings:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:257
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:276
msgid "Failed to read metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:258
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:277
msgid "Failed to read metadata from the following"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:279
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:284
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:298
#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:303
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:322
msgid "Add to library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:284
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:303
#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:116
#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:28
#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:85
@@ -3353,11 +3366,11 @@ msgstr ""
msgid "No book selected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:297
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:316
msgid "The following books are virtual and cannot be added to the calibre library:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:303
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:322
msgid "No book files found"
msgstr ""
@@ -3582,11 +3595,11 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:312
#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:150
#: /home/kovid/work/calibre/src/calibre/gui2/device.py:672
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:905
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:911
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/restore_library.py:101
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/bulk_download.py:186
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:273
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:313
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:276
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:316
msgid "Failed"
msgstr ""
@@ -3643,7 +3656,7 @@ msgid "Bulk convert"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/convert.py:86
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:508
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:505
msgid "Cannot convert"
msgstr ""
@@ -3801,56 +3814,66 @@ msgstr ""
msgid "The selected books will be permanently deleted from your device. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:30
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:31
msgid "Connect to folder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:35
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:36
msgid "Connect to iTunes"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:41
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:42
msgid "Connect to Bambook"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:55
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:63
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:56
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:64
msgid "Start Content Server"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:65
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:66
msgid "Stop Content Server"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:76
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:94
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:77
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:95
msgid "Email to"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:80
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:81
msgid "Email to and delete from library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:88
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:89
msgid "(delete from library)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:103
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:104
msgid "Setup email based sharing of books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:121
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:122
msgid "D"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:121
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:122
msgid "Send to device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:140
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:141
msgid "Connect/share"
msgstr ""
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:174
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:84
+msgid "Stopping"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:175
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:85
+msgid "Stopping server, this could take upto a minute, please wait..."
+msgstr ""
+
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_collections.py:13
msgid "Manage collections"
msgstr ""
@@ -3987,7 +4010,7 @@ msgid "F1"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/help.py:16
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:79
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:91
msgid "Help"
msgstr ""
@@ -4121,7 +4144,7 @@ msgid "Click the show details button to see which ones."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/show_book_details.py:16
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:662
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:696
msgid "Show book details"
msgstr ""
@@ -4456,7 +4479,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:145
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:76
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:375
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1175
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1170
msgid "Path"
msgstr ""
@@ -4473,8 +4496,8 @@ msgid "Formats"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:28
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:986
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1178
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:981
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1173
msgid "Collections"
msgstr ""
@@ -4487,8 +4510,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:367
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:373
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:379
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1184
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1188
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1179
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1183
#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts.py:48
#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts_ui.py:78
#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts_ui.py:83
@@ -4591,7 +4614,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server_ui.py:123
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/template_functions_ui.py:95
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/toolbar_ui.py:98
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:75
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:87
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:123
msgid "Form"
msgstr ""
@@ -6679,7 +6702,7 @@ msgstr ""
#:
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_format_device_ui.py:49
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:76
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1174
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1169
msgid "Format"
msgstr ""
@@ -6856,7 +6879,7 @@ msgstr ""
#:
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:76
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:69
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:984
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:979
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/create_custom_column.py:33
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:295
#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:589
@@ -6884,13 +6907,13 @@ msgstr ""
#:
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog.py:117
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:912
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:916
msgid "Invalid author name"
msgstr ""
#:
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog.py:118
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:913
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:917
msgid "Author names cannot contain & characters."
msgstr ""
@@ -7129,49 +7152,49 @@ msgstr ""
msgid "You must specify a destination when source is a composite field"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:719
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:727
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:838
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:715
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:723
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:844
msgid "Search/replace invalid"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:720
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:716
msgid "Authors cannot be set to the empty string. Book title %s not processed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:728
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:724
msgid "Title cannot be set to the empty string. Book title %s not processed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:839
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:845
msgid "Search pattern is invalid: %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:891
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:897
msgid ""
"Applying changes to %d books.\n"
"Phase {0} {1}%%."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:921
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:927
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:561
msgid "Delete saved search/replace"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:922
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:928
msgid "The selected saved search/replace will be deleted. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:939
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:947
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:945
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:953
msgid "Save search/replace"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:940
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:946
msgid "Search/replace name:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:948
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:954
msgid "That saved search/replace already exists and will be overwritten. Are you sure?"
msgstr ""
@@ -8348,12 +8371,12 @@ msgid "%s (was %s)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:83
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:902
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:906
msgid "Item is blank"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:84
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:903
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:907
msgid "An item cannot be set to nothing. Delete it instead."
msgstr ""
@@ -8869,7 +8892,7 @@ msgid "Show books in the main memory of the device"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:67
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:913
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:924
msgid "Card A"
msgstr ""
@@ -8878,7 +8901,7 @@ msgid "Show books in storage card A"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:69
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:915
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:926
msgid "Card B"
msgstr ""
@@ -8957,33 +8980,33 @@ msgid "Book %s of %s."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:735
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1294
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:599
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1289
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:601
msgid "The lookup/search name is \"{0}\""
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:741
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1296
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1291
msgid "This book's UUID is \"{0}\""
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:981
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:976
msgid "In Library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:985
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:980
msgid "Size"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1194
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1189
msgid "Book %s of %s."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1274
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1269
msgid "Marked for deletion"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1277
+#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1272
msgid "Double click to edit me
"
msgstr ""
@@ -9315,7 +9338,7 @@ msgid "Successfully downloaded metadata for %d out of %d books"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/bulk_download.py:294
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:661
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:695
msgid "Details"
msgstr ""
@@ -9637,12 +9660,12 @@ msgid "You must enter at least one value for enumeration columns"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/create_custom_column.py:172
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/create_custom_column.py:171
msgid "You cannot provide the empty value, as it is included by default"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/create_custom_column.py:176
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/create_custom_column.py:175
msgid "The value \"{0}\" is in the list more than once"
msgstr ""
@@ -9935,7 +9958,7 @@ msgid "Change &font (needs restart)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:223
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:84
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:96
msgid "&Apply"
msgstr ""
@@ -9964,7 +9987,7 @@ msgid "The changes you have made require calibre be restarted immediately. You w
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:331
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:120
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:132
msgid "Restart needed"
msgstr ""
@@ -10387,19 +10410,19 @@ msgid "Here you can control how calibre will save your books when you click the
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:75
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:381
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:378
msgid "Failed to start content server"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:99
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:111
msgid "Error log:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:106
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:118
msgid "Access log:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:121
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:133
msgid "You need to restart the server for changes to take effect"
msgstr ""
@@ -10683,44 +10706,44 @@ msgstr ""
msgid "Add/edit tweaks for any custom plugins you have installed. Documentation for these tweaks should be available on the website from where you downloaded the plugins."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:274
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:314
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:277
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:317
msgid "There was a syntax error in your tweak. Click the show details button for details."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:327
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:330
msgid "Invalid tweaks"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:328
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:331
msgid "The tweaks you entered are invalid, try resetting the tweaks to default and changing them one by one until you find the invalid setting."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:76
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:88
msgid "Values for the tweaks are shown below. Edit them to change the behavior of calibre. Your changes will only take effect after a restart of calibre."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:77
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:89
msgid "Edit tweaks for any custom plugins you have installed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:78
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:90
msgid "&Plugin tweaks"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:80
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:92
msgid "Edit tweak"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:81
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:93
msgid "Restore this tweak to its default value"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:82
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:94
msgid "Restore &default"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:83
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:95
msgid "Apply any changes you made to this tweak"
msgstr ""
@@ -10751,16 +10774,16 @@ msgstr ""
msgid "Restrict to"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:18
-#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:68
+#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:19
+#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:59
msgid "(all books)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:62
+#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:54
msgid "({0} of {1})"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:70
+#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:61
msgid "({0} of all)"
msgstr ""
@@ -10819,90 +10842,90 @@ msgstr ""
msgid "&Alternate shortcut:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:280
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:282
msgid "Rename %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:284
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:286
msgid "Edit sort for %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:289
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:291
msgid "Search for %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:294
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:296
msgid "Search for everything but %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:300
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:302
msgid "Hide category %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:303
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:305
msgid "Show category"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:311
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:313
msgid "Search for books in category %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:315
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:317
msgid "Search for books not in category %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:322
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:326
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:324
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:328
msgid "Manage %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:329
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:331
msgid "Manage Saved Searches"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:336
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:340
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:338
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:342
msgid "Manage User Categories"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:347
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:349
msgid "Show all categories"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:350
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:352
msgid "Change sub-categorization scheme"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:595
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:597
msgid "The grouped search term name is \"{0}\""
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:687
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:689
msgid "Changing the authors for several books can take a while. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:692
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:694
msgid "Changing the metadata for that many books can take a while. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:768
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:361
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:772
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:372
msgid "Searches"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:917
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:921
msgid "Duplicate search name"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:918
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:922
msgid "The saved search name %s is already used."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1339
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1343
msgid "Find item in tag browser"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1342
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1346
msgid ""
"Search for items. This is a \"contains\" search; items containing the\n"
"text anywhere in the name will be found. You can limit the search\n"
@@ -10912,59 +10935,59 @@ msgid ""
"containing the text \"foo\""
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1351
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1355
msgid "ALT+f"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1355
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1359
msgid "F&ind"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1356
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1360
msgid "Find the first/next matching item"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1363
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1367
msgid "Collapse all categories"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1384
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1388
msgid "No More Matches. Click Find again to go to first match"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1397
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1401
msgid "Sort by name"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1397
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1401
msgid "Sort by popularity"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1398
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1402
msgid "Sort by average rating"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1401
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1405
msgid "Set the sort order for entries in the Tag Browser"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1407
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1411
msgid "Match all"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1407
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1411
msgid "Match any"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1412
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1416
msgid "When selecting multiple entries in the Tag Browser match any or all of them"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1416
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1420
msgid "Manage &user categories"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1419
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1423
msgid "Add your own categories to the Tag Browser"
msgstr ""
@@ -11006,62 +11029,62 @@ msgstr ""
msgid "The following books have already been converted to %s format. Do you wish to reconvert them?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:192
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:188
msgid "&Restore"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:194
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:190
msgid "&Donate to support calibre"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:198
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:194
msgid "&Eject connected device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:243
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:239
msgid "Calibre Quick Start Guide"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:305
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:301
msgid "Debug mode"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:306
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:302
msgid "You have started calibre in debug mode. After you quit calibre, the debug log will be available in the file: %s
The log will be displayed automatically."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:496
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:493
msgid "Conversion Error"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:519
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:516
msgid "Recipe Disabled"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:535
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:532
msgid "Failed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:572
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:569
msgid "is the result of the efforts of many volunteers from all over the world. If you find it useful, please consider donating to support its development. Your donation helps keep calibre development going."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:598
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:595
msgid "There are active jobs. Are you sure you want to quit?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:601
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:598
msgid ""
" is communicating with the device!
\n"
" Quitting may cause corruption on the device.
\n"
" Are you sure you want to quit?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:605
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:602
msgid "Active jobs"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:671
+#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:668
msgid "will keep running in the system tray. To close it, choose Quit in the context menu of the system tray."
msgstr ""
@@ -11856,50 +11879,50 @@ msgstr ""
msgid "Turn on the &content server"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:311
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:312
msgid "today"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:314
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:315
msgid "yesterday"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:317
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:318
msgid "thismonth"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:320
#: /home/kovid/work/calibre/src/calibre/library/caches.py:321
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:322
msgid "daysago"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:559
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:569
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:560
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:570
msgid "unchecked"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:559
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:569
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:560
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:570
#: /home/kovid/work/calibre/src/calibre/library/save_to_disk.py:192
msgid "no"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:562
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:572
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:563
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:573
msgid "checked"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:562
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:572
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:563
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:573
#: /home/kovid/work/calibre/src/calibre/library/save_to_disk.py:192
msgid "yes"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:566
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:567
msgid "blank"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/caches.py:566
+#: /home/kovid/work/calibre/src/calibre/library/caches.py:567
msgid "empty"
msgstr ""
@@ -12657,19 +12680,19 @@ msgstr ""
msgid "%sAverage rating is %3.1f"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:911
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:922
msgid "Main"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:2722
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:2733
msgid "
Migrating old database to ebook library in %s
"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:2751
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:2762
msgid "Copying %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:2768
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:2779
msgid "Compacting database"
msgstr ""
@@ -12913,35 +12936,35 @@ msgstr ""
msgid "Books in"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:636
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:670
msgid "Other formats"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:643
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:677
msgid "Read %(title)s in the %(fmt)s format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:648
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:682
msgid "Get"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:663
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:697
msgid "Permalink"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:664
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:698
msgid "A permanent link to this book"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:675
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:709
msgid "This book has been deleted"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:759
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:795
msgid "in search"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:761
+#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:797
msgid "Matching books"
msgstr ""
diff --git a/src/calibre/translations/es.po b/src/calibre/translations/es.po
index 6ed00defb7..a16c4cdf40 100644
--- a/src/calibre/translations/es.po
+++ b/src/calibre/translations/es.po
@@ -11,13 +11,13 @@ msgstr ""
"Project-Id-Version: es\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-15 18:45+0000\n"
-"PO-Revision-Date: 2011-02-16 09:51+0000\n"
+"PO-Revision-Date: 2011-02-17 14:40+0000\n"
"Last-Translator: Jellby \n"
"Language-Team: Spanish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2011-02-17 04:35+0000\n"
+"X-Launchpad-Export-Date: 2011-02-18 04:33+0000\n"
"X-Generator: Launchpad (build 12351)\n"
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:527
@@ -2111,7 +2111,7 @@ msgid ""
msgstr ""
"Transliterar caracteres unicode a la representación ASCII. Tenga cuidado al "
"usar esta opción, ya que reemplazará los caracteres unicode con ASCII. Por "
-"ejemplo, sustituirá «%s%» por «Mikhail Gorbachiov». Tenga en cuenta también "
+"ejemplo, sustituirá «%s» por «Mikhail Gorbachiov». Tenga en cuenta también "
"que en los casos en los que existen múltiples representaciones para un "
"carácter (caracteres compartidos por la escritura china y japonesa, por "
"ejemplo) se usará la representación basada en el idioma de la interfaz de "
@@ -4039,6 +4039,19 @@ msgid ""
"* off: Don't modify the paragraph structure. This is useful when combined "
"with Markdown or Textile formatting to ensure no formatting is lost."
msgstr ""
+"Estructura de párrafos.\n"
+"las opciones son [«auto», «block», «single», «print», «unformatted», «off»]\n"
+"* auto: Intenta detectar automáticamente el tipo de párrafo.\n"
+"* block: Considera cada línea en blanco como un salto de párrafo.\n"
+"* single: Considera cada línea como un párrafo distinto.\n"
+"* print: Considera que cada línea que comienza con dos o más espacios o una "
+"tabulación empieza un párrafo.\n"
+"* unformatted: Casi todas las líneas tienen saltos forzados, con poca o "
+"ninguna sangría. Intenta determinar la estructura y aplicar formato a los "
+"distintos elementos.\n"
+"* off: No se modifica la estructura de párrafos. Esta opción es útil "
+"combinada con el formato Markdown o Textile, para asegurarse de que no se "
+"pierde el formato."
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:43
msgid ""
@@ -4052,6 +4065,15 @@ msgid ""
"* markdown: Processing using markdown formatting. To learn more about "
"markdown see"
msgstr ""
+"Formato usado en el documento.\n"
+"* auto: Decide automáticamente el procesador de formato que se usa.\n"
+"* plain: No procesa el formato del documento. Todo es un párrafo y no se "
+"aplica ningún estilo.\n"
+"* heuristic: Procesa el texto con heurística para determinar formatos como "
+"títulos de capítulo o cursivas.\n"
+"* textile: Procesa el text con formato textile.\n"
+"* markdown: Procesa el texto con formato markdown. Para aprender más sobre "
+"markdown vea\""
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:53
msgid ""
@@ -12368,13 +12390,15 @@ msgstr "&Guardar"
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/search_ui.py:132
msgid "Make &user categories from:"
-msgstr ""
+msgstr "Crear categorías de &usuario a partir de:"
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/search_ui.py:133
msgid ""
"Enter the names of any grouped search terms you wish\n"
"to be shown as user categories"
msgstr ""
+"Introduzca los nombres de los términos agrupados de búsqueda\n"
+"que desea que se muestren como categorías de usuario"
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/sending.py:28
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/sending_ui.py:70
@@ -14574,6 +14598,14 @@ msgid ""
"Select all books by '{0}', apply correct Author Sort value in Edit Metadata "
"dialog, then rebuild the catalog.\n"
msgstr ""
+"Valores de orden de autor inconsistentes para\n"
+"Autor «{0}»:\n"
+"«{1}» <> «{2}»\n"
+"No puede generar el catálogo MOBI.\n"
+"\n"
+"Seleccione todos los libros de «{0}» y establezca el orden de autor "
+"correcto\n"
+"en el cuadro de edición de metadatos, después vuelva a generar el catálogo.\n"
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:1504
msgid ""
@@ -14581,6 +14613,9 @@ msgid ""
"Author '{0}':\n"
"'{1}' <> '{2}'\n"
msgstr ""
+"Aviso: valores de orden de autor inconsistentes para\n"
+"Autor «{0}»:\n"
+"«{1}» <> «{2}»\n"
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:1700
msgid ""
diff --git a/src/calibre/translations/sv.po b/src/calibre/translations/sv.po
index dafeb600a2..8c9d010437 100644
--- a/src/calibre/translations/sv.po
+++ b/src/calibre/translations/sv.po
@@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME \n"
"POT-Creation-Date: 2011-02-15 18:45+0000\n"
-"PO-Revision-Date: 2011-02-13 00:47+0000\n"
-"Last-Translator: Merarom \n"
+"PO-Revision-Date: 2011-02-18 00:52+0000\n"
+"Last-Translator: Kovid Goyal \n"
"Language-Team: Swedish \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2011-02-16 04:45+0000\n"
+"X-Launchpad-Export-Date: 2011-02-18 04:34+0000\n"
"X-Generator: Launchpad (build 12351)\n"
"X-Poedit-Country: SWEDEN\n"
"X-Poedit-Language: Swedish\n"
@@ -7410,7 +7410,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:513
msgid "Apply changes"
-msgstr "Rensa '%s'"
+msgstr "Verkställ ändringar"
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:706
msgid "Remove series"
diff --git a/src/calibre/translations/zh_TW.po b/src/calibre/translations/zh_TW.po
index fbdbfc3d6a..9ae7628dcd 100644
--- a/src/calibre/translations/zh_TW.po
+++ b/src/calibre/translations/zh_TW.po
@@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME \n"
"POT-Creation-Date: 2011-02-15 18:45+0000\n"
-"PO-Revision-Date: 2011-02-16 04:50+0000\n"
+"PO-Revision-Date: 2011-02-17 22:33+0000\n"
"Last-Translator: Chao-Hsiung Liao \n"
"Language-Team: Chinese (traditional)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2011-02-17 04:35+0000\n"
+"X-Launchpad-Export-Date: 2011-02-18 04:34+0000\n"
"X-Generator: Launchpad (build 12351)\n"
"Language: zh_TW\n"
@@ -2070,7 +2070,7 @@ msgstr "正在對電子書籍進行轉換..."
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:1013
msgid "Creating"
-msgstr "建立中"
+msgstr "正在建立"
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/fix/__init__.py:20
msgid "Failed to parse: %s with error: %s"
diff --git a/src/calibre/utils/chm/swig_chm.c b/src/calibre/utils/chm/swig_chm.c
index d86c986b43..80587d7f86 100644
--- a/src/calibre/utils/chm/swig_chm.c
+++ b/src/calibre/utils/chm/swig_chm.c
@@ -164,36 +164,6 @@ SWIG_TypeCast(swig_type_info *ty, void *ptr)
return (*ty->converter)(ptr);
}
-/* Dynamic pointer casting. Down an inheritance hierarchy */
-SWIGRUNTIME(swig_type_info *)
-SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr)
-{
- swig_type_info *lastty = ty;
- if (!ty || !ty->dcast) return ty;
- while (ty && (ty->dcast)) {
- ty = (*ty->dcast)(ptr);
- if (ty) lastty = ty;
- }
- return lastty;
-}
-
-/* Return the name associated with this type */
-SWIGRUNTIME(const char *)
-SWIG_TypeName(const swig_type_info *ty) {
- return ty->name;
-}
-
-/* Search for a swig_type_info structure */
-SWIGRUNTIME(swig_type_info *)
-SWIG_TypeQuery(const char *name) {
- swig_type_info *ty = swig_type_list;
- while (ty) {
- if (ty->str && (strcmp(name,ty->str) == 0)) return ty;
- if (ty->name && (strcmp(name,ty->name) == 0)) return ty;
- ty = ty->prev;
- }
- return 0;
-}
/* Set the clientdata field for a type */
SWIGRUNTIME(void)
@@ -365,21 +335,6 @@ SWIG_newvarlink(void) {
return ((PyObject*) result);
}
-SWIGRUNTIME(void)
-SWIG_addvarlink(PyObject *p, char *name,
- PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) {
- swig_varlinkobject *v;
- swig_globalvar *gv;
- v= (swig_varlinkobject *) p;
- gv = (swig_globalvar *) malloc(sizeof(swig_globalvar));
- gv->name = (char *) malloc(strlen(name)+1);
- strcpy(gv->name,name);
- gv->get_attr = get_attr;
- gv->set_attr = set_attr;
- gv->next = v->vars;
- v->vars = gv;
-}
-
/* Pack binary data into a string */
SWIGRUNTIME(char *)
SWIG_PackData(char *c, void *ptr, int sz) {
@@ -395,29 +350,6 @@ SWIG_PackData(char *c, void *ptr, int sz) {
return c;
}
-/* Unpack binary data from a string */
-SWIGRUNTIME(char *)
-SWIG_UnpackData(char *c, void *ptr, int sz) {
- register unsigned char uu = 0;
- register int d;
- unsigned char *u = (unsigned char *) ptr;
- int i;
- for (i = 0; i < sz; i++, u++) {
- d = *(c++);
- if ((d >= '0') && (d <= '9'))
- uu = ((d - '0') << 4);
- else if ((d >= 'a') && (d <= 'f'))
- uu = ((d - ('a'-10)) << 4);
- d = *(c++);
- if ((d >= '0') && (d <= '9'))
- uu |= (d - '0');
- else if ((d >= 'a') && (d <= 'f'))
- uu |= (d - ('a'-10));
- *u = uu;
- }
- return c;
-}
-
/* Convert a pointer value */
SWIGRUNTIME(int)
SWIG_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) {
@@ -510,39 +442,6 @@ type_error:
return -1;
}
-/* Convert a packed value value */
-SWIGRUNTIME(int)
-SWIG_ConvertPacked(PyObject *obj, void *ptr, int sz, swig_type_info *ty, int flags) {
- swig_type_info *tc;
- char *c;
-
- if ((!obj) || (!PyString_Check(obj))) goto type_error;
- c = PyString_AsString(obj);
- /* Pointer values must start with leading underscore */
- if (*c != '_') goto type_error;
- c++;
- c = SWIG_UnpackData(c,ptr,sz);
- if (ty) {
- tc = SWIG_TypeCheck(c,ty);
- if (!tc) goto type_error;
- }
- return 0;
-
-type_error:
-
- if (flags) {
- if (ty) {
- char *temp = (char *) malloc(64+strlen(ty->name));
- sprintf(temp,"Type error. Expected %s", ty->name);
- PyErr_SetString(PyExc_TypeError, temp);
- free((char *) temp);
- } else {
- PyErr_SetString(PyExc_TypeError,"Expected a pointer");
- }
- }
- return -1;
-}
-
/* Create a new pointer object */
SWIGRUNTIME(PyObject *)
SWIG_NewPointerObj(void *ptr, swig_type_info *type, int own) {
@@ -1071,7 +970,7 @@ static PyObject *_wrap_chm_retrieve_object(PyObject *self, PyObject *args) {
resultobj = PyLong_FromLongLong(result);
{
PyObject *o;
- o = PyString_FromStringAndSize(arg3, arg5);
+ o = PyString_FromStringAndSize((const char *)arg3, arg5);
resultobj = t_output_helper(resultobj,o);