diff --git a/installer/linux/freeze.py b/installer/linux/freeze.py
index 3b272551ff..6e5bb0592b 100644
--- a/installer/linux/freeze.py
+++ b/installer/linux/freeze.py
@@ -9,7 +9,7 @@ Create linux binary.
'''
def freeze():
- import glob, sys, tarfile, os, textwrap, shutil
+ import glob, sys, tarfile, os, textwrap, shutil, platform
from contextlib import closing
from cx_Freeze import Executable, setup
from calibre.constants import __version__, __appname__
@@ -19,6 +19,9 @@ def freeze():
from calibre.ebooks.lrf.fonts import FONT_MAP
import calibre
+ is64bit = platform.architecture()[0] == '64bit'
+ arch = 'x86_64' if is64bit else 'i686'
+
QTDIR = '/usr/lib/qt4'
QTDLLS = ('QtCore', 'QtGui', 'QtNetwork', 'QtSvg', 'QtXml',
@@ -47,7 +50,8 @@ def freeze():
'/usr/lib/libxslt.so.1',
'/usr/lib/libxslt.so.1',
'/usr/lib/libgthread-2.0.so.0',
- '/usr/lib/gcc/i686-pc-linux-gnu/4.3.3/libstdc++.so.6',
+ '/usr/lib/gcc/***-pc-linux-gnu/4.4.1/libstdc++.so.6'.replace('***',
+ arch).replace('i686', 'i486'),
'/usr/lib/libpng12.so.0',
'/usr/lib/libexslt.so.0',
'/usr/lib/libMagickWand.so',
@@ -89,7 +93,7 @@ def freeze():
includes = [x[0] for x in executables.values()]
includes += ['calibre.ebooks.lrf.fonts.prs500.'+x for x in FONT_MAP.values()]
- includes += ['email.iterators', 'email.generator']
+ includes += ['email.iterators', 'email.generator', 'sqlite3.dump']
excludes = ['matplotlib', "Tkconstants", "Tkinter", "tcl", "_imagingtk",
@@ -228,7 +232,8 @@ def freeze():
open(os.path.join(FREEZE_DIR, 'manifest'), 'wb').write('\n'.join(exes))
print 'Creating archive...'
- dist = open(os.path.join(DIST_DIR, 'calibre-%s-i686.tar.bz2'%__version__), 'wb')
+ dist = open(os.path.join(DIST_DIR, 'calibre-%s-%s.tar.bz2'%(__version__,
+ arch)), 'wb')
with closing(tarfile.open(fileobj=dist, mode='w:bz2',
format=tarfile.PAX_FORMAT)) as tf:
for f in walk(FREEZE_DIR):
diff --git a/installer/osx/freeze.py b/installer/osx/freeze.py
index b9dc2ebe39..7791668a09 100644
--- a/installer/osx/freeze.py
+++ b/installer/osx/freeze.py
@@ -353,7 +353,7 @@ def main():
'keyword', 'codeop', 'pydoc', 'readline',
'BeautifulSoup', 'calibre.ebooks.lrf.fonts.prs500.*',
'dateutil', 'email.iterators',
- 'email.generator',
+ 'email.generator', 'sqlite3.dump',
'calibre.ebooks.metadata.amazon',
],
'packages' : ['PIL', 'Authorization', 'lxml', 'dns'],
diff --git a/installer/windows/build_installer.py b/installer/windows/build_installer.py
index 01720bb2c0..24a8768ded 100644
--- a/installer/windows/build_installer.py
+++ b/installer/windows/build_installer.py
@@ -36,7 +36,7 @@ def run_install_jammer(installer_name='<%AppName%>-<%Version%><%Ext%>', build_fo
compression = 'zlib'
if build_for_release:
cmdline += ['--build-for-release']
- #compression = 'lzma (solid)'
+ compression = 'lzma (solid)'
cmdline += ['-DCompressionMethod', compression]
cmdline += ['--build', mpi]
#print 'Running installjammer with cmdline:'
diff --git a/installer/windows/calibre/calibre.mpi b/installer/windows/calibre/calibre.mpi
index a371bb9587..42f30224b0 100644
--- a/installer/windows/calibre/calibre.mpi
+++ b/installer/windows/calibre/calibre.mpi
@@ -232,12 +232,10 @@ test
}
FileGroup ::BEF8D398-58BA-1F66-39D6-D4A63D5BEEF9 -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows TarArchive ZipArchive FreeBSD-5-x86 FreeBSD-6-x86 FreeBSD-7-x86 Linux-x86_64 Solaris-x86} -name {Program Files} -parent FileGroups
File ::8E5D85A4-7608-47A1-CF7C-309060D5FF40 -filemethod {Always overwrite files} -type dir -directory <%InstallDir%> -name /home/kovid/work/calibre/build/py2exe -parent BEF8D398-58BA-1F66-39D6-D4A63D5BEEF9
-File ::FC870EE7-667B-481F-113B-B4504DFCCFA5 -type dir -name bin -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::377C588B-B324-CA09-ED49-4DB5F82A15ED -type dir -name etc -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::55DE4B9F-0881-FF51-E2BA-EC72B5D3425C -type dir -name fonts -parent 377C588B-B324-CA09-ED49-4DB5F82A15ED
File ::A27B68D9-43A6-B994-3091-E829AFBA340D -type dir -name conf.d -parent 55DE4B9F-0881-FF51-E2BA-EC72B5D3425C
File ::974ADD48-88E5-BC7A-1963-928A245F133A -type dir -name conf.avail -parent 55DE4B9F-0881-FF51-E2BA-EC72B5D3425C
-File ::5E5273D8-3423-8DC8-83C4-BE000069A803 -name fonts.dtd -parent 55DE4B9F-0881-FF51-E2BA-EC72B5D3425C
File ::32D7DBE0-E0B1-5BDD-66C5-2A13D8BC8F90 -name fonts.conf -parent 55DE4B9F-0881-FF51-E2BA-EC72B5D3425C
File ::B95D03D4-EA59-F00E-59E1-BA05758879DA -type dir -name imageformats -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::A624029D-AE0F-49A5-4DAC-7720CDCAB271 -name qmng4.dll -parent B95D03D4-EA59-F00E-59E1-BA05758879DA
@@ -337,7 +335,6 @@ File ::2F90282D-B59F-B6BA-090B-45858AF7F3B2 -name IM_MOD_RL_clipboard_.dll -pare
File ::B512D139-B295-D7C3-F0B4-43775849CF58 -name numpy.core._sort.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::A2C063AC-2F12-9260-501A-0E8BD0B8A932 -name calibre.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::439B6D05-7DE6-061D-4BCC-3F04F4FA2FA2 -name IM_MOD_RL_png_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
-File ::BA464D11-BBCE-DEDA-C354-0C7BE60FAA05 -name IM_MOD_RL_braille_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::8F9FF823-AF6D-A288-8AE6-7D74F55DCE29 -name CORE_RL_bzlib_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::57A3F5D5-BFC8-CB38-5A57-548EE0DB033B -name QtNetwork4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::4DB7E8DE-905A-822A-AF14-17BD5ACEF915 -name IM_MOD_RL_wmf_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
@@ -361,7 +358,6 @@ File ::A6419A84-6C22-784E-6D84-D09972770770 -name unicodedata.pyd -parent 8E5D85
File ::E658FBE0-5860-D041-12D3-76ADD18F804B -name servicemanager.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::C98A6FC4-E341-7FD4-005C-DA2B384E11D8 -name win32api.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::ADA36EEA-7DE1-447C-B1AB-A4908E65E2CD -name IM_MOD_RL_ipl_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
-File ::53C2EC15-850F-8F49-6425-C228FB6E6D0E -name libfontconfig-1.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::EDE6F457-C83F-C5FA-9AF4-38FDFF17D929 -name PIL._imagingtk.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::09D0906E-3611-3DB7-32CF-A140585694A7 -name win32pdh.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::4C84F0DC-7157-0C90-2062-180139B03E25 -name IM_MOD_RL_rgb_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
@@ -384,17 +380,14 @@ File ::404A98F1-84FD-B6D0-B130-354EECD9253C -name IM_MOD_RL_emf_.dll -parent 8E5
File ::17034C34-403E-B405-99C1-F80B7F00E27C -name log.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::34E63A2C-65C5-0A84-ACF1-BD6A844D4579 -name pythoncom26.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::2F20484B-53B8-B08E-B691-C5B2D49A9CB4 -name QtWebKit4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
-File ::8AF134C8-9189-3F9A-A081-9143FFD44C45 -name freetype6.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::E8A4442D-D0D3-31CD-997A-3CEB641CF5B7 -name IM_MOD_RL_mtv_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::0CA87D0B-5A04-1439-AEE8-C97072D47BA7 -name CORE_RL_tiff_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::AC24F520-88D4-D1CF-5797-27C715CE8ACA -name pyexpat.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::16848F38-71CD-55B8-4D96-1537F6773744 -name IM_MOD_RL_dps_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
-File ::33A46CC5-BAC4-5863-C83D-303DCCA0CAA1 -name tk85.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::81116DD3-1715-AA87-472F-544FC616EDAF -name IM_MOD_RL_dcm_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::335A4CFB-5C2D-44E4-C438-7018E8244C3D -name ebook-viewer.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::62A16C3B-ED9C-5187-2807-58857DF3A990 -name calibre-debug.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::55ECA7B7-279A-F51D-81C2-C8DC44CF0E22 -name select.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
-File ::A6AF5ECC-A981-4CBD-DBEE-303A9340C603 -name IM_MOD_RL_xps_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::5BCBF71F-18E7-5C52-E3F5-7D7F3028AD46 -name locale.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::5C9FA94C-B8B0-A94B-548D-1D24FDEA5770 -name CORE_RL_wand_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::E39E60BE-DE77-AB8C-42C6-5A7D7DC073E3 -name IM_MOD_RL_ttf_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
@@ -443,12 +436,10 @@ File ::396B4F78-FB45-C0B2-ACB3-97769CF5CD5D -name msvcr90.dll -parent 8E5D85A4-7
File ::1DE767EE-4891-4E54-422D-67A4DFF8C3B5 -name lrfviewer.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::AFFEC28A-615C-E3E6-0026-CCE2594A6D25 -name calibre-server.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::2C64F86B-9366-B52D-F7B2-5BBD51F6982A -name IM_MOD_RL_pwp_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
-File ::F4B2EF9C-EB18-B865-6E99-75CFB9B60D87 -name IM_MOD_RL_dds_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::38770D87-6CA9-9E3E-FBA1-A8CCFCD88FB5 -name IM_MOD_RL_fpx_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::BE2D7BC3-D294-AF3F-65E7-3B372DEFDE36 -name PIL._imaging.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::200B9AEC-809F-75B7-DC12-A51BFC2A6F93 -name PyQt4.QtSvg.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::52132A31-D3AE-C617-7568-BF2AF46B5D74 -name IM_MOD_RL_pcl_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
-File ::F94472C3-C8D0-950F-5ED9-1611D1CE30E5 -name IM_MOD_RL_inline_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::055ADB4B-20C5-E071-442F-4DA0A8D6F3C5 -name english.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::B10B6B91-0C03-642D-90D8-37B607B164AD -name IM_MOD_RL_wpg_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::BFBB144B-1794-8304-9772-F103A42F2CA4 -name IM_MOD_RL_pdb_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
@@ -503,7 +494,6 @@ File ::9BA85EE5-1754-67AF-736D-481CDCC72DD2 -name _imagingft.pyd -parent 8E5D85A
File ::6254DD0C-8F2C-D4AE-2107-2597D542C181 -name IM_MOD_RL_matte_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::F159D566-88D6-C347-3E3C-55C2DDFC5FD0 -name IM_MOD_RL_mono_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::B873CAA2-011F-94C3-7977-FF344E53C44F -name CORE_RL_jbig_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
-File ::7004FCB8-C6F4-C7AF-08E4-B6151B2F7050 -name tcl85.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::6921F62A-4015-4C9F-98A6-BCBBC43B698E -name msvcm90.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::7276E0CA-C205-4B18-19A3-157F1B8523FB -name IM_MOD_RL_xtrn_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::7B9624A9-88B4-C61E-6771-9A34FB6CA3B5 -name PyQt4.QtGui.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
@@ -567,6 +557,15 @@ File ::9E4E5E8F-30C0-E631-9516-2AE01A5CA0E9 -name ebook-device.exe.local -parent
File ::7BE6B538-70D5-A7EB-5F91-E14CE57B394B -name calibre-complete.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::C4E40030-3EE0-8B05-E6B9-89E81433EE1F -name phonon4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
File ::9E84342F-36ED-7ED3-8F90-1EC55267BCFC -name poppler-qt4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
+File ::86BA442C-90C9-A4E6-1D3E-D144E5F326C1 -name msvcp71.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
+File ::11FBAD0B-A2DB-C28A-85B8-D6A22706864F -name mfc71.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
+File ::4B9FB3E6-B807-65CC-826D-A398E964D00C -name IM_MOD_RL_hdf_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
+File ::3E201C0C-C7CC-5785-74F6-A6CC7F50A15A -name msvcr71.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
+File ::2EE42149-1C12-CCA9-9089-AE1809098D0A -name jpeg62.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
+File ::B1FD37B4-E91B-DC1C-1C69-FB2E10EB93AE -name libtiff3.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
+File ::15E09D95-97D6-92A9-CC4D-120885E4DDAD -name freetype.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
+File ::D954BC75-8166-EC1B-D91B-C9779248AA14 -name fontconfig.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
+File ::1F3C052A-A5E0-5C65-8D42-EBF44FBE138D -name podofo.dll.manifest -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40
Component ::F6829AB7-9F66-4CEE-CA0E-21F54C6D3609 -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows FreeBSD-5-x86 FreeBSD-6-x86 FreeBSD-7-x86 Linux-x86_64 Solaris-x86} -name Main -parent Components
SetupType ::D9ADE41C-B744-690C-2CED-CF826BF03D2E -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows FreeBSD-5-x86 FreeBSD-6-x86 FreeBSD-7-x86 Linux-x86_64 Solaris-x86} -name Typical -parent SetupTypes
diff --git a/installer/windows/freeze.py b/installer/windows/freeze.py
index 4dadc8875c..0b4f18ff4a 100644
--- a/installer/windows/freeze.py
+++ b/installer/windows/freeze.py
@@ -7,15 +7,12 @@ __docformat__ = 'restructuredtext en'
Freeze app into executable using py2exe.
'''
QT_DIR = 'C:\\Qt\\4.5.2'
-LIBUSB_DIR = 'C:\\libusb'
+LIBUSB_DIR = r'C:\cygwin\home\kovid\win32\libusb'
LIBUNRAR = 'C:\\Program Files\\UnrarDLL\\unrar.dll'
-PDFTOHTML = 'C:\\cygwin\\home\\kovid\\poppler-0.10.6\\rel\\pdftohtml.exe'
-POPPLER = 'C:\\cygwin\\home\\kovid\\poppler'
-IMAGEMAGICK_DIR = 'C:\\ImageMagick'
-PDFTK = 'C:\\pdftk.exe'
-PODOFO = 'C:\\podofo'
-FONTCONFIG_DIR = 'C:\\fontconfig'
-VC90 = r'C:\VC90.CRT'
+BINARIES = r'C:\cygwin\home\kovid\win32\bin'
+IMAGEMAGICK_DIR = r'C:\cygwin\home\kovid\win32\imagemagick'
+FONTCONFIG_DIR = r'C:\cygwin\home\kovid\win32\etc'
+VC90 = r'C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT'
# ModuleFinder can't handle runtime changes to __path__, but win32com uses them
import sys
@@ -98,25 +95,17 @@ class BuildEXE(py2exe.build_exe.py2exe):
shutil.copyfile(f, os.path.join(tdir, os.path.basename(f)))
print '\tAdding unrar'
shutil.copyfile(LIBUNRAR, os.path.join(PY2EXE_DIR, os.path.basename(LIBUNRAR)))
- print '\tAdding poppler'
- for x in ('bin\\pdftohtml.exe', 'bin\\poppler-qt4.dll',
- 'bin\\freetype.dll', 'bin\\jpeg62.dll'):
- shutil.copyfile(os.path.join(POPPLER, x),
- os.path.join(PY2EXE_DIR, os.path.basename(x)))
- print '\tAdding podofo'
- for f in glob.glob(os.path.join(PODOFO, '*.dll')):
- shutil.copyfile(f, os.path.join(PY2EXE_DIR, os.path.basename(f)))
-
+ print '\tAdding Binaries'
+ for x in glob.glob(os.path.join(BINARIES, '*.dll')) + \
+ [os.path.join(BINARIES, 'pdftohtml.exe')] + \
+ glob.glob(os.path.join(BINARIES, '*.manifest')):
+ shutil.copyfile(x, os.path.join(PY2EXE_DIR, os.path.basename(x)))
print '\tAdding ImageMagick'
for f in os.listdir(IMAGEMAGICK_DIR):
shutil.copyfile(os.path.join(IMAGEMAGICK_DIR, f), os.path.join(PY2EXE_DIR, f))
print '\tCopying fontconfig'
- for f in glob.glob(os.path.join(FONTCONFIG_DIR, '*')):
- tgt = os.path.join(PY2EXE_DIR, os.path.basename(f))
- if os.path.isdir(f):
- shutil.copytree(f, tgt)
- else:
- shutil.copyfile(f, tgt)
+ tgt = os.path.join(PY2EXE_DIR, 'etc')
+ shutil.copytree(FONTCONFIG_DIR, tgt)
print
print 'Doing DLL redirection' # See http://msdn.microsoft.com/en-us/library/ms682600(VS.85).aspx
@@ -169,8 +158,7 @@ def main(args=sys.argv):
'email.iterators',
'email.generator',
'win32process', 'win32api', 'msvcrt',
- 'win32event', 'calibre.ebooks.lrf.any.*',
- 'calibre.ebooks.lrf.feeds.*',
+ 'win32event', 'sqlite3.dump',
'BeautifulSoup', 'pyreadline',
'pydoc', 'IPython.Extensions.*',
'calibre.web.feeds.recipes.*',
@@ -183,7 +171,8 @@ def main(args=sys.argv):
'excludes' : ["Tkconstants", "Tkinter", "tcl",
"_imagingtk", "ImageTk", "FixTk"
],
- 'dll_excludes' : ['mswsock.dll'],
+ 'dll_excludes' : ['mswsock.dll', 'tcl85.dll',
+ 'MSVCP90.dll', 'tk85.dll'],
},
},
diff --git a/setup.py b/setup.py
index 439eef6ce2..a7d5b009ab 100644
--- a/setup.py
+++ b/setup.py
@@ -71,7 +71,7 @@ if __name__ == '__main__':
tag_release, upload_demo, build_linux, build_windows, \
build_osx, upload_installers, upload_user_manual, \
upload_to_pypi, stage3, stage2, stage1, upload, \
- upload_rss, betas
+ upload_rss, betas, build_linux32, build_linux64
entry_points['console_scripts'].append(
'calibre_postinstall = calibre.linux:post_install')
@@ -94,8 +94,8 @@ if __name__ == '__main__':
sources=['src/calibre/utils/windows/winutil.c'],
libraries=['shell32', 'setupapi'],
include_dirs=os.environ.get('INCLUDE',
- 'C:/WinDDK/6001.18001/inc/api/;'
- 'C:/WinDDK/6001.18001/inc/crt/').split(';'),
+ 'C:/WinDDK/7600.16385.0/inc/api/;'
+ 'C:/WinDDK/7600.16385.0/inc/crt/').split(';'),
extra_compile_args=['/X']
))
@@ -103,8 +103,8 @@ if __name__ == '__main__':
poppler_lib = '/usr/lib'
poppler_libs = []
if iswindows:
- poppler_inc = r'C:\cygwin\home\kovid\poppler\include\poppler\qt4'
- poppler_lib = r'C:\cygwin\home\kovid\poppler\lib'
+ poppler_inc = r'C:\cygwin\home\kovid\win32\include\poppler\qt4'
+ poppler_lib = r'C:\cygwin\home\kovid\win32\lib'
poppler_libs = ['QtCore4', 'QtGui4']
if isosx:
poppler_inc = '/Volumes/sw/build/poppler-0.10.7/qt4/src'
@@ -124,9 +124,10 @@ if __name__ == '__main__':
print 'POPPLER_LIB_DIR environment variables.'
podofo_inc = '/usr/include/podofo' if islinux else \
- 'C:\\podofo\\include\\podofo' if iswindows else \
+ r'C:\cygwin\home\kovid\win32\include\podofo' if iswindows else \
'/usr/local/include/podofo'
- podofo_lib = '/usr/lib' if islinux else r'C:\podofo' if iswindows else \
+ podofo_lib = '/usr/lib' if islinux else \
+ r'C:\cygwin\home\kovid\win32\lib' if iswindows else \
'/usr/local/lib'
podofo_inc = os.environ.get('PODOFO_INC_DIR', podofo_inc)
if os.path.exists(os.path.join(podofo_inc, 'podofo.h')):
@@ -141,10 +142,10 @@ if __name__ == '__main__':
print 'PODOFO_LIB_DIR environment variables.'
fc_inc = '/usr/include/fontconfig' if islinux else \
- r'C:\cygwin\home\kovid\fontconfig\include\fontconfig' if iswindows else \
+ r'C:\cygwin\home\kovid\win32\include\fontconfig' if iswindows else \
'/Users/kovid/fontconfig/include/fontconfig'
fc_lib = '/usr/lib' if islinux else \
- r'C:\cygwin\home\kovid\fontconfig\lib' if iswindows else \
+ r'C:\cygwin\home\kovid\win32\lib' if iswindows else \
'/Users/kovid/fontconfig/lib'
@@ -258,6 +259,8 @@ if __name__ == '__main__':
'tag_release' : tag_release,
'upload_demo' : upload_demo,
'build_linux' : build_linux,
+ 'build_linux32' : build_linux32,
+ 'build_linux64' : build_linux64,
'build_windows' : build_windows,
'build_osx' : build_osx,
'upload_installers': upload_installers,
diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py
index 2932d71064..bfe101ffa7 100644
--- a/src/calibre/__init__.py
+++ b/src/calibre/__init__.py
@@ -69,7 +69,7 @@ def osx_version():
return int(m.group(1)), int(m.group(2)), int(m.group(3))
-_filename_sanitize = re.compile(r'[\xae\0\\|\?\*<":>\+\[\]/]')
+_filename_sanitize = re.compile(r'[\xae\0\\|\?\*<":>\+/]')
def sanitize_file_name(name, substitute='_', as_unicode=False):
'''
diff --git a/src/calibre/debug.py b/src/calibre/debug.py
index b7fb55f4aa..0b17920cd8 100644
--- a/src/calibre/debug.py
+++ b/src/calibre/debug.py
@@ -135,7 +135,8 @@ def debug_device_driver():
print 'failed'
continue
success = True
- print 'Main memory:', repr(dev._main_prefix)
+ if hasattr(dev, '_main_prefix'):
+ print 'Main memory:', repr(dev._main_prefix)
print 'Total space:', dev.total_space()
break
if not success and errors:
@@ -144,6 +145,10 @@ def debug_device_driver():
print dev
print msg
print
+ if isosx and os.path.exists('/tmp/ioreg.txt'):
+ print
+ print
+ print "Don't forget to send the file /tmp/ioreg.txt as well"
def add_simple_plugin(path_to_plugin):
diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py
index e2bd1128f5..2261d071ed 100644
--- a/src/calibre/ebooks/conversion/plumber.py
+++ b/src/calibre/ebooks/conversion/plumber.py
@@ -46,7 +46,8 @@ class Plumber(object):
'tags', 'book_producer', 'language'
]
- def __init__(self, input, output, log, report_progress=DummyReporter(), dummy=False):
+ def __init__(self, input, output, log, report_progress=DummyReporter(),
+ dummy=False, merge_plugin_recs=True):
'''
:param input: Path to input file.
:param output: Path to output file/directory
@@ -483,7 +484,8 @@ OptionRecommendation(name='language',
for x in getattr(self, w):
temp.add(x.clone())
setattr(self, w, temp)
- self.merge_plugin_recommendations()
+ if merge_plugin_recs:
+ self.merge_plugin_recommendations()
@classmethod
def unarchive(self, path, tdir):
diff --git a/src/calibre/ebooks/epub/output.py b/src/calibre/ebooks/epub/output.py
index 8955906501..6c38a7d4d3 100644
--- a/src/calibre/ebooks/epub/output.py
+++ b/src/calibre/ebooks/epub/output.py
@@ -78,7 +78,7 @@ class EPUBOutput(OutputFormatPlugin):
),
OptionRecommendation(name='no_default_epub_cover', recommended_value=False,
- help=_('Normally, if the input file ahs no cover and you don\'t'
+ help=_('Normally, if the input file has no cover and you don\'t'
' specify one, a default cover is generated with the title, '
'authors, etc. This option disables the generation of this cover.')),
diff --git a/src/calibre/ebooks/fb2/output.py b/src/calibre/ebooks/fb2/output.py
index 67ea135c1b..2bb49318af 100644
--- a/src/calibre/ebooks/fb2/output.py
+++ b/src/calibre/ebooks/fb2/output.py
@@ -18,10 +18,10 @@ class FB2Output(OutputFormatPlugin):
options = set([
OptionRecommendation(name='inline_toc',
recommended_value=False, level=OptionRecommendation.LOW,
- help=_('Add Table of Contents to begenning of the book.')),
+ help=_('Add Table of Contents to beginning of the book.')),
])
- def convert(self, oeb_book, output_path, input_plugin, opts, log):
+ def convert(self, oeb_book, output_path, input_plugin, opts, log):
fb2mlizer = FB2MLizer(log)
fb2_content = fb2mlizer.extract_content(oeb_book, opts)
@@ -33,11 +33,11 @@ class FB2Output(OutputFormatPlugin):
out_stream = open(output_path, 'wb')
else:
out_stream = output_path
-
+
out_stream.seek(0)
out_stream.truncate()
out_stream.write(fb2_content.encode('utf-8', 'replace'))
-
+
if close:
out_stream.close()
diff --git a/src/calibre/ebooks/metadata/google_books.py b/src/calibre/ebooks/metadata/google_books.py
index 82f11c2010..374c4a8a5f 100644
--- a/src/calibre/ebooks/metadata/google_books.py
+++ b/src/calibre/ebooks/metadata/google_books.py
@@ -6,6 +6,7 @@ __docformat__ = 'restructuredtext en'
import sys, textwrap
from urllib import urlencode
from functools import partial
+from datetime import datetime
from lxml import etree
from dateutil import parser
@@ -151,7 +152,9 @@ class ResultList(list):
try:
d = date(entry)
if d:
- d = parser.parse(d[0].text)
+ default = datetime.utcnow()
+ default = datetime(default.year, default.month, 1)
+ d = parser.parse(d[0].text, default=default)
else:
d = None
except:
diff --git a/src/calibre/ebooks/oeb/stylizer.py b/src/calibre/ebooks/oeb/stylizer.py
index 0c387e3e84..b5d351f886 100644
--- a/src/calibre/ebooks/oeb/stylizer.py
+++ b/src/calibre/ebooks/oeb/stylizer.py
@@ -92,7 +92,10 @@ class CSSSelector(etree.XPath):
def __init__(self, css, namespaces=XPNSMAP):
css = self.MIN_SPACE_RE.sub(r'\1', css)
- path = css_to_xpath(css)
+ try:
+ path = css_to_xpath(css)
+ except UnicodeEncodeError: # Bug in css_to_xpath
+ path = '/'
path = self.LOCAL_NAME_RE.sub(r"local-name() = '", path)
etree.XPath.__init__(self, path, namespaces=namespaces)
self.css = css
diff --git a/src/calibre/ebooks/pdb/output.py b/src/calibre/ebooks/pdb/output.py
index 9a844d2136..06f2f20d10 100644
--- a/src/calibre/ebooks/pdb/output.py
+++ b/src/calibre/ebooks/pdb/output.py
@@ -29,7 +29,7 @@ class PDBOutput(OutputFormatPlugin):
'formats.')),
OptionRecommendation(name='inline_toc',
recommended_value=False, level=OptionRecommendation.LOW,
- help=_('Add Table of Contents to begenning of the book.')),
+ help=_('Add Table of Contents to beginning of the book.')),
])
def convert(self, oeb_book, output_path, input_plugin, opts, log):
diff --git a/src/calibre/ebooks/pml/output.py b/src/calibre/ebooks/pml/output.py
index 970bcd3594..360e63c98e 100644
--- a/src/calibre/ebooks/pml/output.py
+++ b/src/calibre/ebooks/pml/output.py
@@ -34,7 +34,7 @@ class PMLOutput(OutputFormatPlugin):
'The default is cp1252.')),
OptionRecommendation(name='inline_toc',
recommended_value=False, level=OptionRecommendation.LOW,
- help=_('Add Table of Contents to begenning of the book.')),
+ help=_('Add Table of Contents to beginning of the book.')),
])
def convert(self, oeb_book, output_path, input_plugin, opts, log):
diff --git a/src/calibre/ebooks/rb/output.py b/src/calibre/ebooks/rb/output.py
index 0e0bd27326..a16e408b0f 100644
--- a/src/calibre/ebooks/rb/output.py
+++ b/src/calibre/ebooks/rb/output.py
@@ -18,7 +18,7 @@ class RBOutput(OutputFormatPlugin):
options = set([
OptionRecommendation(name='inline_toc',
recommended_value=False, level=OptionRecommendation.LOW,
- help=_('Add Table of Contents to begenning of the book.')),
+ help=_('Add Table of Contents to beginning of the book.')),
])
def convert(self, oeb_book, output_path, input_plugin, opts, log):
diff --git a/src/calibre/ebooks/txt/output.py b/src/calibre/ebooks/txt/output.py
index 38d1b3ebb7..6f0a768b8f 100644
--- a/src/calibre/ebooks/txt/output.py
+++ b/src/calibre/ebooks/txt/output.py
@@ -32,13 +32,13 @@ class TXTOutput(OutputFormatPlugin):
'formats.')),
OptionRecommendation(name='inline_toc',
recommended_value=False, level=OptionRecommendation.LOW,
- help=_('Add Table of Contents to begenning of the book.')),
+ help=_('Add Table of Contents to beginning of the book.')),
])
def convert(self, oeb_book, output_path, input_plugin, opts, log):
writer = TXTMLizer(log)
txt = writer.extract_content(oeb_book, opts)
-
+
log.debug('\tReplacing newlines with selected type...')
txt = specified_newlines(TxtNewlines(opts.newline).newline, txt)
diff --git a/src/calibre/ebooks/txt/txtml.py b/src/calibre/ebooks/txt/txtml.py
index 09f9d5d50c..206dff50ed 100644
--- a/src/calibre/ebooks/txt/txtml.py
+++ b/src/calibre/ebooks/txt/txtml.py
@@ -32,7 +32,7 @@ BLOCK_STYLES = [
]
class TXTMLizer(object):
-
+
def __init__(self, log):
self.log = log
@@ -91,7 +91,7 @@ class TXTMLizer(object):
# Remove excessive newlines.
text = re.sub('\n[ ]+\n', '\n\n', text)
- text = re.sub('\n{5,}', '\n\n\n\n', text)
+ text = re.sub('\n{3,}', '\n\n', text)
# Replace spaces at the beginning and end of lines
text = re.sub('(?imu)^[ ]+', '', text)
diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py
index eb93602fd1..8564fda328 100644
--- a/src/calibre/gui2/__init__.py
+++ b/src/calibre/gui2/__init__.py
@@ -450,12 +450,13 @@ class FileDialog(QObject):
if os.path.exists(f):
self.selected_files.append(f)
if self.selected_files:
- self.selected_files = [qstring_to_unicode(q) for q in self.selected_files]
- dynamic[self.dialog_name] = os.path.dirname(self.selected_files[0])
+ self.selected_files = [unicode(q) for q in self.selected_files]
+ saved_loc = self.selected_files[0]
+ if os.path.isfile(saved_loc):
+ saved_loc = os.path.dirname(saved_loc)
+ dynamic[self.dialog_name] = saved_loc
self.accepted = bool(self.selected_files)
-
-
def get_files(self):
if islinux and self.fd.result() != self.fd.Accepted:
return tuple()
diff --git a/src/calibre/gui2/add.py b/src/calibre/gui2/add.py
index 56ed9b661a..93bebf593f 100644
--- a/src/calibre/gui2/add.py
+++ b/src/calibre/gui2/add.py
@@ -5,7 +5,8 @@ import os, shutil, time
from Queue import Queue, Empty
from threading import Thread
-from PyQt4.Qt import QThread, SIGNAL, QObject, QTimer, Qt
+from PyQt4.Qt import QThread, SIGNAL, QObject, QTimer, Qt, \
+ QProgressDialog
from calibre.gui2.dialogs.progress import ProgressDialog
from calibre.gui2 import question_dialog, error_dialog
@@ -13,6 +14,25 @@ from calibre.ebooks.metadata.opf2 import OPF
from calibre.ebooks.metadata import MetaInformation
from calibre.constants import preferred_encoding
+class DuplicatesAdder(QThread):
+
+ def __init__(self, parent, db, duplicates, db_adder):
+ QThread.__init__(self, parent)
+ self.db, self.db_adder = db, db_adder
+ self.duplicates = duplicates
+
+ def run(self):
+ count = 1
+ for mi, cover, formats in self.duplicates:
+ id = self.db.create_book_entry(mi, cover=cover,
+ add_duplicates=True)
+ self.db_adder.add_formats(id, formats)
+ self.db_adder.number_of_books_added += 1
+ self.emit(SIGNAL('added(PyQt_PyObject)'), count)
+ count += 1
+ self.emit(SIGNAL('adding_done()'))
+
+
class RecursiveFind(QThread):
def __init__(self, parent, db, root, single):
@@ -196,15 +216,19 @@ class Adder(QObject):
self.callback(self.paths, self.names, self.infos)
self.callback_called = True
+ def duplicates_processed(self):
+ self.db_adder.end = True
+ if not self.callback_called:
+ self.callback(self.paths, self.names, self.infos)
+ self.callback_called = True
+ if hasattr(self, '__p_d'):
+ self.__p_d.hide()
+
def update(self):
if self.entry_count <= 0:
self.timer.stop()
- self.process_duplicates()
self.pd.hide()
- self.db_adder.end = True
- if not self.callback_called:
- self.callback(self.paths, self.names, self.infos)
- self.callback_called = True
+ self.process_duplicates()
return
try:
@@ -240,18 +264,28 @@ class Adder(QObject):
def process_duplicates(self):
duplicates = self.db_adder.duplicates
if not duplicates:
- return
+ return self.duplicates_processed()
self.pd.hide()
files = [x[0].title for x in duplicates]
if question_dialog(self._parent, _('Duplicates found!'),
_('Books with the same title as the following already '
'exist in the database. Add them anyway?'),
'\n'.join(files)):
- for mi, cover, formats in duplicates:
- id = self.db.create_book_entry(mi, cover=cover,
- add_duplicates=True)
- self.db_adder.add_formats(id, formats)
- self.db_adder.number_of_books_added += 1
+ pd = QProgressDialog(_('Adding duplicates...'), '', 0, len(duplicates),
+ self._parent)
+ pd.setCancelButton(None)
+ pd.setValue(0)
+ pd.show()
+ self.__p_d = pd
+ self.__d_a = DuplicatesAdder(self._parent, self.db, duplicates,
+ self.db_adder)
+ self.connect(self.__d_a, SIGNAL('added(PyQt_PyObject)'),
+ pd.setValue)
+ self.connect(self.__d_a, SIGNAL('adding_done()'),
+ self.duplicates_processed)
+ self.__d_a.start()
+ else:
+ return self.duplicates_processed()
def cleanup(self):
if hasattr(self, 'pd'):
diff --git a/src/calibre/gui2/convert/__init__.py b/src/calibre/gui2/convert/__init__.py
index 70223acb70..bbab3a1edd 100644
--- a/src/calibre/gui2/convert/__init__.py
+++ b/src/calibre/gui2/convert/__init__.py
@@ -34,7 +34,7 @@ class Widget(QWidget):
def initialize_options(self, get_option, get_help, db=None, book_id=None):
'''
:param get_option: A callable that takes one argument: the option name
- and returns the correspoing OptionRecommendation.
+ and returns the corresponding OptionRecommendation.
:param get_help: A callable that takes the option name and return a help
string.
'''
diff --git a/src/calibre/gui2/convert/structure_detection.py b/src/calibre/gui2/convert/structure_detection.py
index 506ee37c45..00c5e30d6b 100644
--- a/src/calibre/gui2/convert/structure_detection.py
+++ b/src/calibre/gui2/convert/structure_detection.py
@@ -28,11 +28,12 @@ class StructureDetectionWidget(Widget, Ui_Form):
'remove_footer', 'footer_regex']
)
self.db, self.book_id = db, book_id
+ for x in ('pagebreak', 'rule', 'both', 'none'):
+ self.opt_chapter_mark.addItem(x)
self.initialize_options(get_option, get_help, db, book_id)
self.opt_chapter.set_msg(_('Detect chapters at (XPath expression):'))
self.opt_page_breaks_before.set_msg(_('Insert page breaks before '
'(XPath expression):'))
-
def pre_commit_check(self):
for x in ('header_regex', 'footer_regex'):
x = getattr(self, 'opt_'+x)
diff --git a/src/calibre/gui2/convert/structure_detection.ui b/src/calibre/gui2/convert/structure_detection.ui
index eebc0f0d53..6952abce96 100644
--- a/src/calibre/gui2/convert/structure_detection.ui
+++ b/src/calibre/gui2/convert/structure_detection.ui
@@ -29,26 +29,6 @@
-
-
- pagebreak
-
-
-
-
- rule
-
-
-
-
- both
-
-
-
-
- none
-
-
diff --git a/src/calibre/gui2/dialogs/add_save.py b/src/calibre/gui2/dialogs/add_save.py
deleted file mode 100644
index 7bd6273b4a..0000000000
--- a/src/calibre/gui2/dialogs/add_save.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python
-# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
-from __future__ import with_statement
-
-__license__ = 'GPL v3'
-__copyright__ = '2009, Kovid Goyal '
-__docformat__ = 'restructuredtext en'
-
-import textwrap
-
-from PyQt4.Qt import QTabWidget
-
-from calibre.gui2.dialogs.add_save_ui import Ui_TabWidget
-from calibre.library.save_to_disk import config, FORMAT_ARG_DESCS
-
-
-class AddSave(QTabWidget, Ui_TabWidget):
-
- def __init__(self, parent=None):
- QTabWidget.__init__(self, parent)
- self.setupUi(self)
- c = config()
- opts = c.parse()
- for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf'):
- g = getattr(self, 'opt_'+x)
- g.setChecked(getattr(opts, x))
- help = '\n'.join(textwrap.wrap(c.get_option(x).help, 75))
- g.setToolTip(help)
- g.setWhatsThis(help)
-
- for x in ('formats', 'timefmt'):
- g = getattr(self, 'opt_'+x)
- g.setText(getattr(opts, x))
- help = '\n'.join(textwrap.wrap(c.get_option(x).help, 75))
- g.setToolTip(help)
- g.setWhatsThis(help)
-
- help = '\n'.join(textwrap.wrap(c.get_option('template').help, 75))
- self.opt_template.initialize('save_to_disk_template_history',
- opts.template, help=help)
-
- variables = sorted(FORMAT_ARG_DESCS.keys())
- rows = []
- for var in variables:
- rows.append(u'
%s
%s
'%
- (var, FORMAT_ARG_DESCS[var]))
- table = u'
%s
'%(u'\n'.join(rows))
- self.template_variables.setText(table)
-
- def save_settings(self):
- c = config()
- for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf'):
- c.set(x, getattr(self, 'opt_'+x).isChecked())
- for x in ('formats', 'template', 'timefmt'):
- c.set(x, unicode(getattr(self, 'opt_'+x).text()).strip())
-
-
-
-if __name__ == '__main__':
- from PyQt4.Qt import QApplication
- app=QApplication([])
- a = AddSave()
- a.show()
- app.exec_()
- a.save_settings()
-
diff --git a/src/calibre/gui2/dialogs/config/__init__.py b/src/calibre/gui2/dialogs/config/__init__.py
index d719f24d66..6cc77725e8 100644
--- a/src/calibre/gui2/dialogs/config/__init__.py
+++ b/src/calibre/gui2/dialogs/config/__init__.py
@@ -41,7 +41,8 @@ class ConfigTabs(QTabWidget):
log = Log()
log.outputs = []
- self.plumber = Plumber('dummy.epub', 'dummy.epub', log, dummy=True)
+ self.plumber = Plumber('dummy.epub', 'dummy.epub', log, dummy=True,
+ merge_plugin_recs=False)
def widget_factory(cls):
return cls(self, self.plumber.get_option_by_name,
@@ -298,7 +299,8 @@ class EmailAccounts(QAbstractTableModel):
while y in self.accounts:
c += 1
y = x + str(c)
- self.accounts[y] = ['MOBI, EPUB', True,
+ auto_send = len(self.accounts) < 1
+ self.accounts[y] = ['MOBI, EPUB', auto_send,
len(self.account_order) == 0]
self.account_order = sorted(self.accounts.keys())
self.reset()
@@ -756,7 +758,8 @@ class CheckIntegrity(QProgressDialog):
def __init__(self, db, parent=None):
QProgressDialog.__init__(self, parent)
- self.setCancelButtonText('')
+ self.db = db
+ self.setCancelButton(None)
self.setMinimum(0)
self.setMaximum(100)
self.setWindowTitle(_('Checking database integrity'))
diff --git a/src/calibre/gui2/dialogs/config/add_save.py b/src/calibre/gui2/dialogs/config/add_save.py
index 6d91745044..71e7c83a62 100644
--- a/src/calibre/gui2/dialogs/config/add_save.py
+++ b/src/calibre/gui2/dialogs/config/add_save.py
@@ -26,7 +26,8 @@ class AddSave(QTabWidget, Ui_TabWidget):
self.removeTab(2)
c = config()
opts = c.parse()
- for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf'):
+ for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf',
+ 'replace_whitespace', 'to_lowercase'):
g = getattr(self, 'opt_'+x)
g.setChecked(getattr(opts, x))
help = '\n'.join(textwrap.wrap(c.get_option(x).help, 75))
@@ -74,7 +75,8 @@ class AddSave(QTabWidget, Ui_TabWidget):
if not self.validate():
return False
c = config()
- for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf'):
+ for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf',
+ 'replace_whitespace', 'to_lowercase'):
c.set(x, getattr(self, 'opt_'+x).isChecked())
for x in ('formats', 'template', 'timefmt'):
c.set(x, unicode(getattr(self, 'opt_'+x).text()).strip())
diff --git a/src/calibre/gui2/dialogs/config/add_save.ui b/src/calibre/gui2/dialogs/config/add_save.ui
index 6faec64626..513be73e54 100644
--- a/src/calibre/gui2/dialogs/config/add_save.ui
+++ b/src/calibre/gui2/dialogs/config/add_save.ui
@@ -77,14 +77,14 @@
-
+ Save &cover separately
-
+ Update &metadata in saved copies
@@ -163,6 +163,20 @@
+
+
+
+ Replace space with &underscores
+
+
+
+
+
+
+ Change paths to &lowercase
+
+
+
diff --git a/src/calibre/gui2/images/news/axxon_news.png b/src/calibre/gui2/images/news/axxon_news.png
new file mode 100644
index 0000000000..c8b62364ef
Binary files /dev/null and b/src/calibre/gui2/images/news/axxon_news.png differ
diff --git a/src/calibre/gui2/images/news/darknet.png b/src/calibre/gui2/images/news/darknet.png
new file mode 100644
index 0000000000..a64867c3e7
Binary files /dev/null and b/src/calibre/gui2/images/news/darknet.png differ
diff --git a/src/calibre/gui2/images/news/livemint.png b/src/calibre/gui2/images/news/livemint.png
new file mode 100644
index 0000000000..5fb3cf7e89
Binary files /dev/null and b/src/calibre/gui2/images/news/livemint.png differ
diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py
index 98ae6a3796..8d2abd77d7 100644
--- a/src/calibre/gui2/main.py
+++ b/src/calibre/gui2/main.py
@@ -14,8 +14,9 @@ from PyQt4.Qt import Qt, SIGNAL, QObject, QCoreApplication, QUrl, QTimer, \
QMessageBox, QStackedLayout
from PyQt4.QtSvg import QSvgRenderer
-from calibre import __version__, __appname__, \
- iswindows, isosx, prints, patheq
+from calibre import prints, patheq
+from calibre.constants import __version__, __appname__, \
+ iswindows, isosx, filesystem_encoding
from calibre.utils.filenames import ascii_filename
from calibre.ptempfile import PersistentTemporaryFile
from calibre.utils.config import prefs, dynamic
@@ -424,9 +425,18 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
error_dialog(self, _('Bad database location'),
_('Bad database location')+':'+self.library_path,
det_msg=traceback.format_exc()).exec_()
+ fname = _('Calibre Library')
+ if isinstance(fname, unicode):
+ try:
+ fname = fname.encode(filesystem_encoding)
+ except:
+ fname = 'Calibre Library'
+ x = os.path.expanduser('~'+os.sep+fname)
+ if not os.path.exists(x):
+ os.makedirs(x)
dir = unicode(QFileDialog.getExistingDirectory(self,
_('Choose a location for your ebook library.'),
- os.path.expanduser('~')))
+ x))
if not dir:
QCoreApplication.exit(1)
raise SystemExit(1)
@@ -1493,6 +1503,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.search.clear_to_help()
self.status_bar.reset_info()
self.library_view.sortByColumn(3, Qt.DescendingOrder)
+ self.library_view.model().count_changed()
############################################################################
@@ -1565,14 +1576,23 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.device_error_dialog.show()
def job_exception(self, job):
+ if not hasattr(self, '_modeless_dialogs'):
+ self._modeless_dialogs = []
+ if self.isVisible():
+ for x in list(self._modeless_dialogs):
+ if not x.isVisible():
+ self._modeless_dialogs.remove(x)
try:
if 'calibre.ebooks.DRMError' in job.details:
- error_dialog(self, _('Conversion Error'),
+ d = error_dialog(self, _('Conversion Error'),
_('
Could not convert: %s
It is a '
'DRMed book. You must first remove the '
'DRM using 3rd party tools.')%\
(job.description.split(':')[-1],
- 'http://wiki.mobileread.com/wiki/DRM')).exec_()
+ 'http://wiki.mobileread.com/wiki/DRM'))
+ d.setModal(False)
+ d.show()
+ self._modeless_dialogs.append(d)
return
except:
pass
@@ -1582,9 +1602,12 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
prints(job.details, file=sys.stderr)
except:
pass
- error_dialog(self, _('Conversion Error'),
+ d = error_dialog(self, _('Conversion Error'),
_('Failed')+': '+unicode(job.description),
- det_msg=job.details).exec_()
+ det_msg=job.details)
+ d.setModal(False)
+ d.show()
+ self._modeless_dialogs.append(d)
def initialize_database(self):
diff --git a/src/calibre/gui2/tag_view.py b/src/calibre/gui2/tag_view.py
index 2e8bf3c910..9adbb5aad6 100644
--- a/src/calibre/gui2/tag_view.py
+++ b/src/calibre/gui2/tag_view.py
@@ -93,7 +93,7 @@ class TagsModel(QStandardItemModel):
QIcon(':/images/minus.svg')]
QStandardItemModel.__init__(self)
self.db = db
- self.ignore_next_search = False
+ self.ignore_next_search = 0
self._data = {}
self.bold_font = QFont()
self.bold_font.setBold(True)
@@ -129,19 +129,20 @@ class TagsModel(QStandardItemModel):
self.refresh()
def reinit(self, *args, **kwargs):
- if not self.ignore_next_search:
+ if self.ignore_next_search == 0:
for category in self._data.values():
for tag in category:
tag.state = 0
self.reset()
- self.ignore_next_search = False
+ else:
+ self.ignore_next_search -= 1
def toggle(self, index):
if index.parent().isValid():
category = self.row_map[index.parent().row()]
tag = self._data[category][index.row()]
self.invisibleRootItem().child(index.parent().row()).child(index.row()).toggle()
- self.ignore_next_search = True
+ self.ignore_next_search = 2
self.emit(SIGNAL('dataChanged(QModelIndex,QModelIndex)'), index, index)
return True
return False
diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py
index 68e866e7e1..7045f6334d 100644
--- a/src/calibre/gui2/wizard/__init__.py
+++ b/src/calibre/gui2/wizard/__init__.py
@@ -17,6 +17,7 @@ from calibre import __appname__, patheq
from calibre.library.database2 import LibraryDatabase2
from calibre.library.move import MoveLibrary
from calibre.resources import server_resources
+from calibre.constants import filesystem_encoding
from calibre.gui2.wizard.send_email import smtp_prefs
from calibre.gui2.wizard.device_ui import Ui_WizardPage as DeviceUI
from calibre.gui2.wizard.library_ui import Ui_WizardPage as LibraryUI
@@ -423,7 +424,8 @@ def move_library(oldloc, newloc, parent, callback_on_complete):
callback)
else:
rq = Queue()
- m = MoveLibrary(oldloc, newloc, db.data.count(), rq)
+ m = MoveLibrary(oldloc, newloc,
+ len(db.get_top_level_move_items()[0]), rq)
global _mm
_mm = MoveMonitor(m, rq, callback, parent)
return
@@ -473,7 +475,18 @@ class LibraryPage(QWizardPage, LibraryUI):
def initializePage(self):
lp = prefs['library_path']
if not lp:
- lp = os.path.expanduser('~')
+ fname = _('Calibre Library')
+ if isinstance(fname, unicode):
+ try:
+ fname = fname.encode(filesystem_encoding)
+ except:
+ fname = 'Calibre Library'
+ lp = os.path.expanduser('~'+os.sep+fname)
+ if not os.path.exists(lp):
+ try:
+ os.makedirs(lp)
+ except:
+ lp = os.path.expanduser('~')
self.location.setText(lp)
def isComplete(self):
diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py
index 81d293a1cb..0a392c1b8c 100644
--- a/src/calibre/library/cli.py
+++ b/src/calibre/library/cli.py
@@ -183,9 +183,7 @@ def do_list(db, fields, sort_by, ascending, search_text, line_width, separator,
return template.generate(id="urn:calibre:main", data=data, subtitle=subtitle,
sep=os.sep, quote=quote, updated=db.last_modified()).render('xml')
-
-
-def command_list(args, dbpath):
+def list_option_parser():
parser = get_parser(_(
'''\
%prog list [options]
@@ -208,6 +206,11 @@ List the books available in the calibre database.
of = ['text', 'xml', 'stanza']
parser.add_option('--output-format', choices=of, default='text',
help=_('The format in which to output the data. Available choices: %s. Defaults is text.')%of)
+ return parser
+
+
+def command_list(args, dbpath):
+ parser = list_option_parser()
opts, args = parser.parse_args(sys.argv[:1] + args)
fields = [str(f.strip().lower()) for f in opts.fields.split(',')]
if 'all' in fields:
@@ -316,9 +319,7 @@ def do_add(db, paths, one_book_per_directory, recurse, add_duplicates):
finally:
sys.stdout = orig
-
-
-def command_add(args, dbpath):
+def add_option_parser():
parser = get_parser(_(
'''\
%prog add [options] file1 file2 file3 ...
@@ -333,6 +334,11 @@ the directory related options below.
help=_('Process directories recursively'))
parser.add_option('-d', '--duplicates', action='store_true', default=False,
help=_('Add books to database even if they already exist. Comparison is done based on book titles.'))
+ return parser
+
+
+def command_add(args, dbpath):
+ parser = add_option_parser()
opts, args = parser.parse_args(sys.argv[:1] + args)
if len(args) < 2:
parser.print_help()
@@ -353,9 +359,8 @@ def do_remove(db, ids):
if send_message is not None:
send_message('refreshdb:', 'calibre GUI')
-
-def command_remove(args, dbpath):
- parser = get_parser(_(
+def remove_option_parser():
+ return get_parser(_(
'''\
%prog remove ids
@@ -363,6 +368,9 @@ Remove the books identified by ids from the database. ids should be a comma sepa
list of id numbers (you can get id numbers by using the list command). For example, \
23,34,57-85
'''))
+
+def command_remove(args, dbpath):
+ parser = remove_option_parser()
opts, args = parser.parse_args(sys.argv[:1] + args)
if len(args) < 2:
parser.print_help()
@@ -385,15 +393,18 @@ list of id numbers (you can get id numbers by using the list command). For examp
def do_add_format(db, id, fmt, path):
db.add_format_with_hooks(id, fmt.upper(), path, index_is_id=True)
-
-def command_add_format(args, dbpath):
- parser = get_parser(_(
+def add_format_option_parser():
+ return get_parser(_(
'''\
%prog add_format [options] id ebook_file
Add the ebook in ebook_file to the available formats for the logical book identified \
by id. You can get id by using the list command. If the format already exists, it is replaced.
'''))
+
+
+def command_add_format(args, dbpath):
+ parser = add_format_option_parser()
opts, args = parser.parse_args(sys.argv[:1] + args)
if len(args) < 3:
parser.print_help()
@@ -410,8 +421,8 @@ by id. You can get id by using the list command. If the format already exists, i
def do_remove_format(db, id, fmt):
db.remove_format(id, fmt, index_is_id=True)
-def command_remove_format(args, dbpath):
- parser = get_parser(_(
+def remove_format_option_parser():
+ return get_parser(_(
'''
%prog remove_format [options] id fmt
@@ -420,6 +431,10 @@ You can get id by using the list command. fmt should be a file extension \
like LRF or TXT or EPUB. If the logical book does not have fmt available, \
do nothing.
'''))
+
+
+def command_remove_format(args, dbpath):
+ parser = remove_format_option_parser()
opts, args = parser.parse_args(sys.argv[:1] + args)
if len(args) < 3:
parser.print_help()
@@ -441,7 +456,7 @@ def do_show_metadata(db, id, as_opf):
else:
print unicode(mi).encode(preferred_encoding)
-def command_show_metadata(args, dbpath):
+def show_metadata_option_parser():
parser = get_parser(_(
'''
%prog show_metadata [options] id
@@ -451,6 +466,10 @@ id is an id number from the list command.
'''))
parser.add_option('--as-opf', default=False, action='store_true',
help=_('Print metadata in OPF form (XML)'))
+ return parser
+
+def command_show_metadata(args, dbpath):
+ parser = show_metadata_option_parser()
opts, args = parser.parse_args(sys.argv[1:]+args)
if len(args) < 2:
parser.print_help()
@@ -468,8 +487,8 @@ def do_set_metadata(db, id, stream):
if send_message is not None:
send_message('refreshdb:', 'calibre GUI')
-def command_set_metadata(args, dbpath):
- parser = get_parser(_(
+def set_metadata_option_parser():
+ return get_parser(_(
'''
%prog set_metadata [options] id /path/to/metadata.opf
@@ -478,6 +497,9 @@ from the OPF file metadata.opf. id is an id number from the list command. You
can get a quick feel for the OPF format by using the --as-opf switch to the
show_metadata command.
'''))
+
+def command_set_metadata(args, dbpath):
+ parser = set_metadata_option_parser()
opts, args = parser.parse_args(sys.argv[1:]+args)
if len(args) < 3:
parser.print_help()
@@ -501,7 +523,7 @@ def do_export(db, ids, dir, opts):
prints('\t'+'\n\t'.join(tb.splitlines()))
prints(' ')
-def command_export(args, dbpath):
+def export_option_parser():
parser = get_parser(_('''\
%prog export [options] ids
@@ -530,6 +552,16 @@ an opf file). You can get id numbers from the list command.
parser.add_option(switch, default=opt.default,
help=opt.help, dest=pref)
+ for pref in ('replace_whitespace', 'to_lowercase'):
+ opt = c.get_option(pref)
+ switch = '--'+pref.replace('_', '-')
+ parser.add_option(switch, default=False, action='store_true',
+ help=opt.help)
+
+ return parser
+
+def command_export(args, dbpath):
+ parser = export_option_parser()
opts, args = parser.parse_args(sys.argv[1:]+args)
if (len(args) < 2 and not opts.all):
parser.print_help()
@@ -541,9 +573,11 @@ an opf file). You can get id numbers from the list command.
do_export(get_db(dbpath, opts), ids, dir, opts)
return 0
-def main(args=sys.argv):
- commands = ('list', 'add', 'remove', 'add_format', 'remove_format',
+COMMANDS = ('list', 'add', 'remove', 'add_format', 'remove_format',
'show_metadata', 'set_metadata', 'export')
+
+
+def option_parser():
parser = OptionParser(_(
'''\
%%prog command [options] [arguments]
@@ -555,11 +589,16 @@ command is one of:
For help on an individual command: %%prog command --help
'''
- )%'\n '.join(commands))
+ )%'\n '.join(COMMANDS))
+ return parser
+
+
+def main(args=sys.argv):
+ parser = option_parser()
if len(args) < 2:
parser.print_help()
return 1
- if args[1] not in commands:
+ if args[1] not in COMMANDS:
if args[1] == '--version':
parser.print_version()
return 0
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index c605be0879..54607d1d11 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -1444,14 +1444,33 @@ class LibraryDatabase2(LibraryDatabase):
if notify:
self.notify('add', [id])
+ def get_top_level_move_items(self):
+ items = set(os.listdir(self.library_path))
+ paths = set([])
+ for x in self.data.universal_set():
+ path = self.path(x, index_is_id=True)
+ path = path.split(os.sep)[0]
+ paths.add(path)
+ paths.add('metadata.db')
+ path_map = {}
+ for x in paths:
+ path_map[x] = x
+ if not self.is_case_sensitive:
+ for x in items:
+ path_map[x.lower()] = x
+ items = set(path_map)
+ paths = set([x.lower() for x in paths])
+ items = items.intersection(paths)
+ return items, path_map
+
def move_library_to(self, newloc, progress=lambda x: x):
if not os.path.exists(newloc):
os.makedirs(newloc)
- items = os.listdir(self.library_path)
old_dirs = set([])
- for i, x in enumerate(items):
+ items, path_map = self.get_top_level_move_items()
+ for x in items:
src = os.path.join(self.library_path, x)
- dest = os.path.join(newloc, x)
+ dest = os.path.join(newloc, path_map[x])
if os.path.isdir(src):
if os.path.exists(dest):
shutil.rmtree(dest)
@@ -1461,6 +1480,7 @@ class LibraryDatabase2(LibraryDatabase):
if os.path.exists(dest):
os.remove(dest)
shutil.copyfile(src, dest)
+ x = path_map[x]
if not isinstance(x, unicode):
x = x.decode(filesystem_encoding, 'replace')
progress(x)
@@ -1675,13 +1695,12 @@ books_series_link feeds
user_version = self.user_version
sql = self.conn.dump()
self.conn.close()
- dest = self.dbpath+'.old'
+ dest = self.dbpath+'.tmp'
if os.path.exists(dest):
os.remove(dest)
- shutil.copyfile(self.dbpath, dest)
+ conn = None
try:
- os.remove(self.dbpath)
- ndb = DBThread(self.dbpath, None)
+ ndb = DBThread(dest, None)
ndb.connect()
conn = ndb.conn
conn.executescript(sql)
@@ -1690,15 +1709,21 @@ books_series_link feeds
conn.commit()
conn.close()
except:
- if os.path.exists(self.dbpath):
- os.remove(self.dbpath)
- shutil.copyfile(dest, self.dbpath)
- os.remove(dest)
+ if conn is not None:
+ try:
+ conn.close()
+ except:
+ pass
+ if os.path.exists(dest):
+ os.remove(dest)
raise
else:
- os.remove(dest)
+ os.remove(self.dbpath)
+ shutil.copyfile(dest, self.dbpath)
self.connect()
self.refresh()
+ if os.path.exists(dest):
+ os.remove(dest)
callback(0.1, _('Checking for missing files.'))
bad = {}
us = self.data.universal_set()
diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py
index cafe8addc8..c404bd9223 100644
--- a/src/calibre/library/save_to_disk.py
+++ b/src/calibre/library/save_to_disk.py
@@ -6,7 +6,7 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal '
__docformat__ = 'restructuredtext en'
-import os, traceback, cStringIO
+import os, traceback, cStringIO, re
from calibre.utils.config import Config, StringConfig
from calibre.utils.filenames import shorten_components_to, supports_long_names, \
@@ -17,7 +17,7 @@ from calibre.constants import preferred_encoding, filesystem_encoding
from calibre import strftime
-DEFAULT_TEMPLATE = '{author_sort}/{title} - {authors}'
+DEFAULT_TEMPLATE = '{author_sort}/{title}/{title} - {authors}'
FORMAT_ARG_DESCS = dict(
title=_('The title'),
authors=_('The authors'),
@@ -71,6 +71,10 @@ def config(defaults=None):
x('timefmt', default='%b, %Y',
help=_('The format in which to display dates. %d - day, %b - month, '
'%Y - year. Default is: %b, %Y'))
+ x('to_lowercase', default=False,
+ help=_('Convert paths to lowercase.'))
+ x('replace_whitespace', default=False,
+ help=_('Replace whitespace with underscores.'))
return c
def preprocess_template(template):
@@ -81,7 +85,9 @@ def preprocess_template(template):
template = template.decode(preferred_encoding, 'replace')
return template
-def get_components(template, mi, id, timefmt='%b %Y', length=250, sanitize_func=ascii_filename):
+def get_components(template, mi, id, timefmt='%b %Y', length=250,
+ sanitize_func=ascii_filename, replace_whitespace=False,
+ to_lowercase=False):
format_args = dict(**FORMAT_ARGS)
if mi.title:
format_args['title'] = mi.title
@@ -113,6 +119,11 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250, sanitize_func=
components = [str(id)]
components = [x.encode(filesystem_encoding, 'replace') if isinstance(x,
unicode) else x for x in components]
+ if to_lowercase:
+ components = [x.lower() for x in components]
+ if replace_whitespace:
+ components = [re.sub(r'\s', '_', x) for x in components]
+
return shorten_components_to(length, components)
@@ -134,7 +145,9 @@ def save_book_to_disk(id, db, root, opts, length):
return True, id, mi.title
components = get_components(opts.template, mi, id, opts.timefmt, length,
- ascii_filename if opts.asciiize else sanitize_file_name)
+ ascii_filename if opts.asciiize else sanitize_file_name,
+ to_lowercase=opts.to_lowercase,
+ replace_whitespace=opts.replace_whitespace)
base_path = os.path.join(root, *components)
base_name = os.path.basename(base_path)
dirpath = os.path.dirname(base_path)
diff --git a/src/calibre/library/server.py b/src/calibre/library/server.py
index 10656a6df8..4ab254555e 100644
--- a/src/calibre/library/server.py
+++ b/src/calibre/library/server.py
@@ -110,7 +110,7 @@ class LibraryServer(object):
${authors}urn:calibre:${record[FM['id']]}${timestamp}
-
+
'''))
@@ -120,7 +120,7 @@ class LibraryServer(object):
calibre Library$id${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}
-
+
calibrehttp://calibre.kovidgoyal.net
@@ -140,7 +140,7 @@ class LibraryServer(object):
calibre Library$id${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}
-
+
calibrehttp://calibre.kovidgoyal.net
@@ -152,19 +152,19 @@ class LibraryServer(object):
By Authorurn:uuid:fc000fa0-8c23-11de-a31d-0002a5d5c51b${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}
-
+
By Titleurn:uuid:1df4fe40-8c24-11de-b4c6-0002a5d5c51b${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}
-
+
By Newesturn:uuid:3c6d4940-8c24-11de-a4d7-0002a5d5c51b${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}
-
+
'''))
@@ -460,8 +460,11 @@ class LibraryServer(object):
@expose
def index(self, **kwargs):
'The / URL'
- want_opds = cherrypy.request.headers.get('Stanza-Device-Name', 919) != \
- 919 or cherrypy.request.headers.get('Want-OPDS-Catalog', 919) != 919
+ ua = cherrypy.request.headers.get('User-Agent', '').strip()
+ want_opds = \
+ cherrypy.request.headers.get('Stanza-Device-Name', 919) != 919 or \
+ cherrypy.request.headers.get('Want-OPDS-Catalog', 919) != 919 or \
+ ua.startswith('Stanza')
return self.stanza(search=kwargs.get('search', None), sortby=kwargs.get('sortby',None), authorid=kwargs.get('authorid',None)) if want_opds else self.static('index.html')
diff --git a/src/calibre/library/sqlite.py b/src/calibre/library/sqlite.py
index a1caf506d9..3c23dd67cc 100644
--- a/src/calibre/library/sqlite.py
+++ b/src/calibre/library/sqlite.py
@@ -157,6 +157,8 @@ class DatabaseException(Exception):
def proxy(fn):
''' Decorator to call methods on the database connection in the proxy thread '''
def run(self, *args, **kwargs):
+ if self.closed:
+ raise DatabaseException('Connection closed', '')
with global_lock:
if self.proxy.unhandled_error[0] is not None:
raise DatabaseException(*self.proxy.unhandled_error)
@@ -174,10 +176,12 @@ class ConnectionProxy(object):
def __init__(self, proxy):
self.proxy = proxy
+ self.closed = False
def close(self):
- if self.proxy.unhandled_error is None:
+ if self.proxy.unhandled_error[0] is None:
self.proxy.requests.put((self.proxy.CLOSE, [], {}))
+ self.closed = True
@proxy
def get(self, query, all=True): pass
diff --git a/src/calibre/manual/custom.py b/src/calibre/manual/custom.py
index d5bb7efcec..6e519c9b2b 100644
--- a/src/calibre/manual/custom.py
+++ b/src/calibre/manual/custom.py
@@ -69,6 +69,46 @@ CLI_PREAMBLE='''\
{usage}
'''
+def generate_calibredb_help(preamble, info):
+ from calibre.library.cli import COMMANDS, get_parser
+ import calibre.library.cli as cli
+ preamble = preamble[:preamble.find('\n\n\n', preamble.find('code-block'))]
+ preamble += textwrap.dedent('''
+
+ :command:`calibredb` is the command line interface to the |app| database. It has
+ several sub-commands, documented below:
+
+ ''')
+
+ global_parser = get_parser('')
+ groups = []
+ for grp in global_parser.option_groups:
+ groups.append((grp.title.capitalize(), grp.description, grp.option_list))
+
+ global_options = '\n'.join(render_options('calibredb', groups, False, False))
+
+
+ lines, toc = [], []
+ for cmd in COMMANDS:
+ parser = getattr(cli, cmd+'_option_parser')()
+ toc.append(' * :ref:`calibredb-%s`'%cmd)
+ lines += ['.. _calibredb-'+cmd+':', '']
+ lines += [cmd, '~'*20, '']
+ usage = parser.usage.strip()
+ usage = [i for i in usage.replace('%prog', 'calibredb').splitlines()]
+ cmdline = ' '+usage[0]
+ usage = usage[1:]
+ usage = [i.replace(cmd, ':command:`%s`'%cmd) for i in usage]
+ lines += ['.. code-block:: none', '', cmdline, '']
+ lines += usage
+ groups = [(None, None, parser.option_list)]
+ lines += ['']
+ lines += render_options('calibredb '+cmd, groups, False)
+ lines += ['']
+
+ toc = '\n'.join(toc)
+ raw = preamble + '\n\n'+toc + '\n\n' + global_options+'\n\n'+'\n'.join(lines)
+ update_cli_doc(os.path.join('cli', 'calibredb.rst'), raw, info)
def generate_ebook_convert_help(preamble, info):
from calibre.ebooks.conversion.cli import create_option_parser
@@ -125,11 +165,12 @@ def update_cli_doc(path, raw, info):
info('creating '+os.path.splitext(os.path.basename(path))[0])
open(path, 'wb').write(raw)
-def render_options(cmd, groups, options_header=True):
- lines = []
+def render_options(cmd, groups, options_header=True, add_program=True):
+ lines = ['']
if options_header:
lines = ['[options]', '-'*15, '']
- lines += ['.. program:: '+cmd, '']
+ if add_program:
+ lines += ['.. program:: '+cmd, '']
for title, desc, options in groups:
if title:
lines.extend([title, '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'])
@@ -153,6 +194,7 @@ def cli_docs(app):
for script in entry_points['console_scripts']:
module = script[script.index('=')+1:script.index(':')].strip()
cmd = script[:script.index('=')].strip()
+ if cmd in ('calibre-complete', 'calibre-parallel'): continue
module = __import__(module, fromlist=[module.split('.')[-1]])
if hasattr(module, 'option_parser'):
documented_cmds.append((cmd, getattr(module, 'option_parser')()))
@@ -180,6 +222,8 @@ def cli_docs(app):
preamble = CLI_PREAMBLE.format(cmd=cmd, cmdline=cmdline, usage=usage)
if cmd == 'ebook-convert':
generate_ebook_convert_help(preamble, info)
+ elif cmd == 'calibredb':
+ generate_calibredb_help(preamble, info)
else:
groups = [(None, None, parser.option_list)]
for grp in parser.option_groups:
diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst
index 8b437f174a..36a262ab5c 100644
--- a/src/calibre/manual/faq.rst
+++ b/src/calibre/manual/faq.rst
@@ -54,11 +54,11 @@ In order to convert a collection of HTML files in a specific oder, you have to c
Then just add this HTML file to the GUI and use the convert button to create your ebook.
-How do I convert my file containing non-English characters?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+How do I convert my file containing non-English characters, or smart quotes?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are two aspects to this problem:
1. Knowing the encoding of the source file: |app| tries to guess what character encoding your source files use, but often, this is impossible, so you need to tell it what encoding to use. This can be done in the GUI via the :guilabel:`Input character encoding` field in the :guilabel:`Look & Feel` section. The command-line tools all have an :option:`--input-encoding` option.
- 2. When adding HTML files to |app|, you may need to tell |app| what encoding the files are in. To do this go to Preferences->Plugins->File Type plugins and customize the HTML2Zip plugin, telling it what encoding your HTML files are in. |app| will then automatically convert the HTML files into the UTF-8 encoding when adding them.
+ 2. When adding HTML files to |app|, you may need to tell |app| what encoding the files are in. To do this go to Preferences->Plugins->File Type plugins and customize the HTML2Zip plugin, telling it what encoding your HTML files are in. Now when you add HTML files to |app| they will be correctly processed. HTML files from different sources often have different encodings, so you may have to change this setting repeatedly. A common encoding for many files from the web is ``cp1252`` and I would suggest you try that first.
3. Embedding fonts: If you are generating an LRF file to read on your SONY Reader, you are limited by the fact that the Reader only supports a few non-English characters in the fonts it comes pre-loaded with. You can work around this problem by embedding a unicode-aware font that supports the character set your file uses into the LRF file. You should embed atleast a serif and a sans-serif font. Be aware that embedding fonts significantly slows down page-turn speed on the reader.
@@ -95,13 +95,17 @@ turned into a collection on the reader. Note that the PRS-500 does not support c
How do I use |app| with my iPhone?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-First install the Stanza reader on your iPhone from http://www.lexcycle.com . Then,
+First install the Stanza reader on your iPhone using iTunes.
- * Set the output format for calibre to EPUB (The output format can be set next to the big red heart)
+ * Set the Preferred Output Format in |app| to EPUB (The output format can be set under Preferences->General)
* Convert the books you want to read on your iPhone to EPUB format by selecting them and clicking the Convert button.
* Turn on the Content Server in |app|'s preferences and leave |app| running.
-Now you should be able to access your books on your iPhone.
+Now you should be able to access your books on your iPhone by opening Stanza and going to "Shared Books". Under Shared Books you will see an entry "Book in calibre". If you don't, make sure your iPhone is connected using the WiFi network in your house, not 3G. If the |app| catalog is still not detected in Stanza, you can add it manually in Stanza, by clicking "Online Catalog" and the clicking the plus icon in the lower right corner to add a new catalog. In the Add Catalog screen enter whatever name you like and in the URL field, enter the following::
+
+ http://192.168.1.2:8080/
+
+Replace ``192.168.1.2`` with the local IP address of the computer running |app|. If you have changed the port the |app| content server is running on, you will have to change ``8080`` as well to the new port. The local IP address is the IP address you computer is assigned on your home network. A quick Google search will tell you how to find out your local IP address.
Why is my device not detected in linux?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -136,6 +140,12 @@ Why doesn't |app| have a column for foo?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|app| is designed to have columns for the most frequently and widely used fields. If it does not have a coulmn for your favorite field, you can always add a tag to the book for that piece of information. |app| also supports a general purpose "comments" fields for longer items.
+How do I move my |app| library from one computer to another?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Simply copy the |app| library folder from the old to the new computer. You can find out what the library folder is by clicking Preferences. The very first item is the path tot he library folder. Now on the new computer, start |app| for the first time. It will run the Welcome Wizard asking you for the location of the |app| library. Point it to the previously copied folder.
+
+Note that if you are transferring between different types of computers (for example Windows to OS X) then after doing the above you should also go to Preferences->Advanced and click the Check database integrity button. It will warn you about missing files, if any, which you should then transfer by hand.
+
Content From The Web
---------------------
diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot
index 64111480cd..27084860a1 100644
--- a/src/calibre/translations/calibre.pot
+++ b/src/calibre/translations/calibre.pot
@@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: calibre 0.6.8\n"
-"POT-Creation-Date: 2009-08-21 15:14+MDT\n"
-"PO-Revision-Date: 2009-08-21 15:14+MDT\n"
+"POT-Creation-Date: 2009-08-25 14:07+MDT\n"
+"PO-Revision-Date: 2009-08-25 14:07+MDT\n"
"Last-Translator: Automatically generated\n"
"Language-Team: LANGUAGE\n"
"MIME-Version: 1.0\n"
@@ -72,7 +72,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/jacket.py:86
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/writer.py:105
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/writer.py:106
-#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:26
+#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:33
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/palmdoc/writer.py:29
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ztxt/writer.py:27
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:81
@@ -126,7 +126,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1093
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1423
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1425
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:1514
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:1525
#: /home/kovid/work/calibre/src/calibre/library/server.py:373
#: /home/kovid/work/calibre/src/calibre/library/server.py:446
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
@@ -693,234 +693,234 @@ msgstr ""
msgid "Output saved to"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:68
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:69
msgid "Level of verbosity. Specify multiple times for greater verbosity."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:75
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:76
msgid "Specify the input profile. The input profile gives the conversion system information on how to interpret various information in the input document. For example resolution dependent lengths (i.e. lengths in pixels). Choices are:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:86
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:87
msgid "Specify the output profile. The output profile tells the conversion system how to optimize the created document for the specified device. In some cases, an output profile is required to produce documents that will work on a device. For example EPUB on the SONY reader. Choices are:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:97
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:98
msgid "The base font size in pts. All font sizes in the produced book will be rescaled based on this size. By choosing a larger size you can make the fonts in the output bigger and vice versa. By default, the base font size is chosen based on the output profile you chose."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:107
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:108
msgid "Mapping from CSS font names to font sizes in pts. An example setting is 12,12,14,16,18,20,22,24. These are the mappings for the sizes xx-small to xx-large, with the final size being for huge fonts. The font rescaling algorithm uses these sizes to intelligently rescale fonts. The default is to use a mapping based on the output profile you chose."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:119
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:120
msgid "Disable all rescaling of font sizes."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:126
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:127
msgid "The line height in pts. Controls spacing between consecutive lines of text. By default no line height manipulation is performed."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:134
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:135
msgid "Some badly designed documents use tables to control the layout of text on the page. When converted these documents often have text that runs off the page and other artifacts. This option will extract the content from the tables and present it in a linear fashion."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:144
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:145
msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level one. If this is specified, it takes precedence over other forms of auto-detection."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:153
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:154
msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level two. Each entry is added under the previous level one entry."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:161
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:162
msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level three. Each entry is added under the previous level two entry."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:169
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:170
msgid "Normally, if the source file already has a Table of Contents, it is used in preference to the auto-generated one. With this option, the auto-generated one is always used."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:177
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:178
msgid "Don't add auto-detected chapters to the Table of Contents."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:184
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:185
msgid "If fewer than this number of chapters is detected, then links are added to the Table of Contents. Default: %default"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:191
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:192
msgid "Maximum number of links to insert into the TOC. Set to 0 to disable. Default is: %default. Links are only added to the TOC if less than the threshold number of chapters were detected."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:199
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:200
msgid "Remove entries from the Table of Contents whose titles match the specified regular expression. Matching entries and all their children are removed."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:210
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:211
msgid "An XPath expression to detect chapter titles. The default is to consider
or
tags that contain the words \"chapter\",\"book\",\"section\" or \"part\" as chapter titles as well as any tags that have class=\"chapter\". The expression used must evaluate to a list of elements. To disable chapter detection, use the expression \"/\". See the XPath Tutorial in the calibre User Manual for further help on using this feature."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:224
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:225
msgid "Specify how to mark detected chapters. A value of \"pagebreak\" will insert page breaks before chapters. A value of \"rule\" will insert a line before chapters. A value of \"none\" will disable chapter marking and a value of \"both\" will use both page breaks and lines to mark chapters."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:234
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:235
msgid "Either the path to a CSS stylesheet or raw CSS. This CSS will be appended to the style rules from the source file, so it can be used to override those rules."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:243
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:244
msgid "An XPath expression. Page breaks are inserted before the specified elements."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:249
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:250
msgid "Set the top margin in pts. Default is %default. Note: 72 pts equals 1 inch"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:254
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:255
msgid "Set the bottom margin in pts. Default is %default. Note: 72 pts equals 1 inch"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:259
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:260
msgid "Set the left margin in pts. Default is %default. Note: 72 pts equals 1 inch"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:264
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:265
msgid "Set the right margin in pts. Default is %default. Note: 72 pts equals 1 inch"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:269
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:270
msgid "Do not force text to be justified in output. Whether text is actually displayed justified or not depends on whether the ebook format and reading device support justification."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:276
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:277
msgid "Remove spacing between paragraphs. Also sets an indent on paragraphs of 1.5em. Spacing removal will not work if the source file does not use paragraphs (
or
tags)."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:283
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:284
msgid "Use the cover detected from the source file in preference to the specified cover."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:289
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:290
msgid "Insert a blank line between paragraphs. Will not work if the source file does not use paragraphs (
or
tags)."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:296
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:297
msgid "Remove the first image from the input ebook. Useful if the first image in the source file is a cover and you are specifying an external cover."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:304
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:305
msgid "Insert the book metadata at the start of the book. This is useful if your ebook reader does not support displaying/searching metadata directly."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:312
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:313
msgid "Attempt to detect and correct hard line breaks and other problems in the source file. This may make things worse, so use with care."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:320
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:321
msgid "Use a regular expression to try and remove the header."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:327
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:328
msgid "The regular expression to use to remove the header."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:333
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:334
msgid "Use a regular expression to try and remove the footer."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:340
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:341
msgid "The regular expression to use to remove the footer."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:347
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:348
msgid "Read metadata from the specified OPF file. Metadata read from this file will override any metadata in the source file."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:354
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:355
msgid "Transliterate unicode characters to an ASCII representation. Use with care because this will replace unicode characters with ASCII. For instance it will replace \"%s\" with \"Mikhail Gorbachiov\". Also, note that in cases where there are multiple representations of a character (characters shared by Chinese and Japanese for instance) the representation used by the largest number of people will be used (Chinese in the previous example)."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:369
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:370
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:37
msgid "Set the title."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:373
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:374
msgid "Set the authors. Multiple authors should be separated by ampersands."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:378
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:379
msgid "The version of the title to be used for sorting. "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:382
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:383
msgid "String to be used when sorting by author. "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:386
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:387
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:51
msgid "Set the cover to the specified file."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:390
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:391
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:53
msgid "Set the ebook description."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:394
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:395
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:55
msgid "Set the ebook publisher."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:398
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:399
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:59
msgid "Set the series this ebook belongs to."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:402
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:403
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:61
msgid "Set the index of the book in this series."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:406
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:407
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:63
msgid "Set the rating. Should be a number between 1 and 5."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:410
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:411
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:65
msgid "Set the ISBN of the book."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:414
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:415
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:67
msgid "Set the tags for the book. Should be a comma separated list."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:418
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:419
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:69
msgid "Set the book producer."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:422
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:423
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:71
msgid "Set the language."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:513
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:515
msgid "Could not find an ebook inside the archive"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:651
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:653
msgid "Converting input to HTML..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:668
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:670
msgid "Running transforms on ebook..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:743
+#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:745
msgid "Creating"
msgstr ""
@@ -937,7 +937,7 @@ msgid "Split all HTML files larger than this size (in KB). This is necessary as
msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:81
-msgid "Normally, if the input file ahs no cover and you don't specify one, a default cover is generated with the title, authors, etc. This option disables the generation of this cover."
+msgid "Normally, if the input file has no cover and you don't specify one, a default cover is generated with the title, authors, etc. This option disables the generation of this cover."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/fb2ml.py:123
@@ -956,7 +956,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/pml/output.py:37
#: /home/kovid/work/calibre/src/calibre/ebooks/rb/output.py:21
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:35
-msgid "Add Table of Contents to begenning of the book."
+msgid "Add Table of Contents to beginning of the book."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:242
@@ -1352,27 +1352,27 @@ msgstr ""
msgid "Set the BookID in LRF files"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:143
+#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:144
msgid "No file specified"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:158
+#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:159
msgid "Original metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:175
+#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:176
msgid "Changed metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:187
+#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:188
msgid "OPF created in"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:193
+#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:194
msgid "Cover saved to"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:195
+#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:196
msgid "No cover found"
msgstr ""
@@ -1590,6 +1590,11 @@ msgstr ""
msgid "Sidebar"
msgstr ""
+#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:22
+#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:21
+msgid "Normally calibre treats blank lines as paragraph markers. With this option it will assume that every line represents a paragraph instead."
+msgstr ""
+
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/output.py:23
msgid "Format to use inside the pdb container. Choices are:"
msgstr ""
@@ -1804,10 +1809,6 @@ msgstr ""
msgid "This RTF file has a feature calibre does not support. Convert it to HTML first and then try it."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:21
-msgid "Normally calibre treats blank lines as paragraph markers. With this option it will assume that every line represents a paragraph instead."
-msgstr ""
-
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:24
msgid "Type of newline to use. Options are %s. Default is 'system'. Use 'old_mac' for compatibility with Mac OS 9 and earlier. For Mac OS X use 'unix'. 'system' will default to the newline type used by this OS."
msgstr ""
@@ -1906,7 +1907,7 @@ msgid "Default action to perform when send to device button is clicked"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:124
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:397
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:398
msgid "Copied"
msgstr ""
@@ -1977,6 +1978,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:15
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:20
#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:16
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input.py:13
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:17
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input.py:13
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:18
@@ -1988,6 +1990,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:16
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:13
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input.py:13
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input.py:13
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input.py:13
msgid "input"
@@ -2002,11 +2005,12 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:44
#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:110
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input_ui.py:28
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:35
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:38
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:39
#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output_ui.py:28
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:71
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:61
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:28
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:35
@@ -2250,6 +2254,7 @@ msgid "Set the metadata. The output file will contain as much of this metadata a
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:134
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:95
msgid "Choose cover for "
msgstr ""
@@ -2452,6 +2457,15 @@ msgstr ""
msgid "&Bottom:"
msgstr ""
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input.py:12
+msgid "PDB Input"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input_ui.py:29
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:29
+msgid "Treat each &line as a paragraph"
+msgstr ""
+
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:16
msgid "PDB Output"
msgstr ""
@@ -2522,91 +2536,71 @@ msgstr ""
msgid "Fine tune the detection of chapter headings and other document structure."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:32
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:34
msgid "Detect chapters at (XPath expression):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:33
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:35
msgid "Insert page breaks before (XPath expression):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:43
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:44
#: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:72
msgid "Invalid regular expression"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:44
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:45
#: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:73
msgid "Invalid regular expression: %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:49
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:50
#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:38
msgid "Invalid XPath"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:50
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:51
#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:39
msgid "The XPath expression %s is invalid."
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:72
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:68
msgid "Chapter &mark:"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:73
-msgid "pagebreak"
-msgstr ""
-
-#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:74
-msgid "rule"
-msgstr ""
-
-#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:75
-msgid "both"
-msgstr ""
-
-#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:76
-msgid "none"
-msgstr ""
-
-#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:77
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:69
msgid "Remove first &image"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:78
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:70
msgid "Insert &metadata as page at start of book"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:79
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:71
msgid "&Footer regular expression:"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:80
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:72
msgid "&Preprocess input file to possibly improve structure detection"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:81
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:73
msgid "&Header regular expression:"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:82
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:74
msgid "Remove F&ooter"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:83
+#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:75
msgid "Remove H&eader"
msgstr ""
@@ -2656,10 +2650,6 @@ msgstr ""
msgid "TXT Input"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:29
-msgid "Treat each &line as a paragraph"
-msgstr ""
-
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:16
msgid "TXT Output"
msgstr ""
@@ -2870,7 +2860,7 @@ msgid "Attached, you will find the e-book"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device.py:550
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:175
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:177
msgid "by"
msgstr ""
@@ -2970,7 +2960,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:88
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:89
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:92
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:214
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:216
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:344
#: /home/kovid/work/calibre/src/calibre/gui2/status.py:57
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:83
@@ -3009,166 +2999,173 @@ msgstr ""
msgid "&Profile:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:168
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:170
msgid "%(plugin_type)s %(plugins)s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:169
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:171
msgid "plugins"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:194
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196
msgid "Conversion"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:194
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196
msgid "General"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:194
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196
msgid "Interface"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:195
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:197
msgid "Add/Save"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:195
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:197
msgid ""
"Email\n"
"Delivery"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:198
msgid "Advanced"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:198
msgid ""
"Content\n"
"Server"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:198
msgid "Plugins"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:214
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:216
msgid "Auto send"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:214
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:216
msgid "Email"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:219
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:221
msgid "Formats to email. The first matching format will be sent."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:220
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:222
msgid "If checked, downloaded news will be automatically mailed to this email address (provided it is in one of the listed formats)."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:294
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:296
msgid "new email address"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:505
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:508
msgid "No valid plugin path"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:506
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:509
msgid "%s is not a valid plugin path"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:509
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:512
msgid "Choose plugin"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:521
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:524
msgid "Plugin cannot be disabled"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:522
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:525
msgid "The plugin: %s cannot be disabled"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:531
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:534
msgid "Plugin not customizable"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:532
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:535
msgid "Plugin: %s does not need customization"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:556
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:559
msgid "Customize %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:566
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:569
msgid "Cannot remove builtin plugin"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:567
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:570
msgid " cannot be removed. It is a builtin plugin. Try disabling it instead."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:600
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:603
msgid "Error log:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:607
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:610
msgid "Access log:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:632
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:564
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:635
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:574
msgid "Failed to start content server"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:656
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:469
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:659
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:470
msgid "Select location for books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:673
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:676
msgid "Invalid size"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:674
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:677
msgid "The size %s is invalid. must be of the form widthxheight"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:718
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:723
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:721
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:726
msgid "Invalid database location"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:719
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:722
msgid "Invalid database location "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:720
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:723
msgid " Must be a directory."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:724
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:727
msgid "Invalid database location. Cannot write to "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:749
-msgid "Checking..."
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:764
+msgid "Checking database integrity"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:750
-msgid "Checking database integrity. This may take a while."
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:783
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:142
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1005
+#: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:52
+msgid "Error"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:763
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:784
+msgid "Failed to check database integrity"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:789
msgid "Some inconsistencies found"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:764
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:790
msgid "The following books had formats listed in the database that are not actually available. The entries for the formats have been removed. You should check them manually. This can happen if you manipulate the files in the library folder directly."
msgstr ""
@@ -4452,150 +4449,149 @@ msgstr ""
msgid "Configure"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:58
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:59
msgid "Save single format to disk..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:125
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:126
msgid "Search (For Advanced Search click the button to the left)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:141
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:995
-#: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:52
-msgid "Error"
-msgstr ""
-
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:142
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:143
msgid "Error communicating with device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:156
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:157
msgid "&Restore"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:158
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:159
msgid "&Donate to support calibre"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:163
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:164
msgid "&Restart"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:202
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:203
msgid "
For help visit %s.kovidgoyal.net "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:205
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:206
msgid "%s: %s by Kovid Goyal %%(version)s %%(device)s
"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:225
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:226
msgid "Edit metadata individually"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:227
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:228
msgid "Edit metadata in bulk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:229
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:230
msgid "Download metadata and covers"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:230
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:231
msgid "Download only metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:231
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:232
msgid "Download only covers"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:234
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:235
msgid "Add books from a single directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:235
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:236
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/main.py:238
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:239
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/main.py:241
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:242
msgid "Add Empty book. (Book entry with no formats)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:278
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:279
#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:353
msgid "Save to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:279
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:280
msgid "Save to disk in a single directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:280
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1472
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:281
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1484
msgid "Save only %s format to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:288
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:289
#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:359
msgid "View"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:289
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:290
msgid "View specific format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:315
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:316
msgid "Convert individually"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:316
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:317
msgid "Bulk convert"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:331
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:332
msgid "Run welcome wizard"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:365
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:366
msgid "Similar books..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:424
#: /home/kovid/work/calibre/src/calibre/gui2/main.py:425
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:426
msgid "Bad database location"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/main.py:428
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1600
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:477
+msgid "Calibre Library"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:438
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1612
msgid "Choose a location for your ebook library."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:607
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:617
msgid "Browse by covers"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:714
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:724
msgid "Device: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:716
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:726
msgid " detected."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:738
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:748
msgid "Connected "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:750
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:760
msgid "Device database corrupted"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:751
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:761
msgid ""
"\n"
"
The database of books on the reader is corrupted. Try the following:\n"
@@ -4606,297 +4602,297 @@ msgid ""
" "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:827
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:870
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:837
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:880
msgid "Uploading books to device."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:835
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:845
msgid "Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:836
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:846
msgid "EPUB Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:837
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:847
msgid "LRF Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:838
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:848
msgid "HTML Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:839
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:849
msgid "LIT Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:840
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:850
msgid "MOBI Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:841
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:851
msgid "Text books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:842
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:852
msgid "PDF Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:843
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:853
msgid "Comics"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:844
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:854
msgid "Archives"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:879
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:889
msgid "Failed to read metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:880
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:890
msgid "Failed to read metadata from the following"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:899
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:909
msgid "The selected books will be permanently deleted and the files removed from your computer. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:926
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:936
msgid "Deleting books from device."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:957
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:967
msgid "Cannot download metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:958
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1006
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1036
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1061
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1196
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:968
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1016
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1046
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1071
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1208
msgid "No books selected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:967
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:977
msgid "covers"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:967
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:977
msgid "metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:969
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:979
msgid "Downloading %s for %d book(s)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:990
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1000
msgid "Failed to download some metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:991
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1001
msgid "Failed to download metadata for the following:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:994
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1004
msgid "Failed to download metadata:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1005
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1035
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1015
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1045
msgid "Cannot edit metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1060
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1070
msgid "Cannot save to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1063
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1073
msgid "Choose destination directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1088
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1100
msgid "Error while saving"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1089
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1101
msgid "There was an error while saving."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1096
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1097
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1108
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1109
msgid "Could not save some books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1098
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1110
msgid "Click the show details button to see which ones."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1117
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1129
msgid "Fetching news from "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1130
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1142
msgid " fetched."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1195
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1207
msgid "Cannot convert"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1365
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1384
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1377
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1396
msgid "No book selected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1365
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1417
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1377
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1429
msgid "Cannot view"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1371
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1383
msgid "Choose the format to view"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1383
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1395
msgid "Cannot open folder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1400
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1412
msgid "Multiple Books Selected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1401
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1413
msgid "You are attempting to open %d books. Opening too many books at once can be slow and have a negative effect on the responsiveness of your computer. Once started the process cannot be stopped until complete. Do you wish to continue?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1418
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1430
msgid "%s has no available formats."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1456
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1468
msgid "Cannot configure"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1457
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1469
msgid "Cannot configure while there are running jobs."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1501
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1513
msgid "No detailed info available"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1502
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1514
msgid "No detailed information is available for books on the device."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1550
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1562
msgid "Error talking to device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1551
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1563
msgid "There was a temporary error talking to the device. Please unplug and reconnect the device and or reboot."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1568
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1583
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1580
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1595
msgid "Conversion Error"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1569
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1581
msgid "
Could not convert: %s
It is a DRMed book. You must first remove the DRM using 3rd party tools."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1584
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1596
msgid "Failed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1609
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1621
msgid "Invalid library location"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1610
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1622
msgid "Could not access %s. Using %s as the library."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1658
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1670
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."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1682
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1694
msgid "There are active jobs. Are you sure you want to quit?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1685
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1697
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/main.py:1689
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1701
msgid "WARNING: Active jobs"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1740
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1752
msgid "will keep running in the system tray. To close it, choose Quit in the context menu of the system tray."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1759
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1771
msgid "Latest version: %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1767
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1779
msgid "Update available"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1768
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1780
msgid "%s has been updated to version %s. See the new features. Visit the download page?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1786
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1798
msgid "Use the library located at the specified path."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1788
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1800
msgid "Start minimized to system tray."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1790
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1802
msgid "Log debugging information to console"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1838
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1850
msgid "If you are sure it is not running"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1840
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1852
msgid "Cannot Start "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1841
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1853
msgid "%s is already running."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1844
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1856
msgid "may be running in the system tray, in the"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1846
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1858
msgid "upper right region of the screen."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1848
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1860
msgid "lower right region of the screen."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1851
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1863
msgid "try rebooting your computer."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1853
-#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1873
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1865
+#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1885
msgid "try deleting the file"
msgstr ""
@@ -5505,47 +5501,47 @@ msgstr ""
msgid "Title Case"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:36
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:37
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:149
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:38
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:150
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:151
msgid "Default"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:288
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:289
msgid "If you use the WordPlayer e-book app on your Android phone, you can access your calibre book collection directly on the device. To do this you have to turn on the content server."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:292
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:293
msgid "Remember to leave calibre running as the server only runs as long as calibre is running."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:294
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:295
msgid "You have to add the URL http://myhostname:8080 as your calibre library in WordPlayer. Here myhostname should be the fully qualified hostname or the IP address of the computer calibre is running on."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:371
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:372
msgid "Moving library..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:387
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:388
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:389
msgid "Failed to move library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:441
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:442
msgid "Invalid database"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:442
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:443
msgid "
An invalid library already exists at %s, delete it before trying to move the existing library. Error: %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:453
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:454
msgid "Could not move library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:515
+#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:527
msgid "welcome wizard"
msgstr ""
@@ -5958,18 +5954,30 @@ msgid ""
"For help on an individual command: %%prog command --help\n"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/library/database2.py:1540
+#: /home/kovid/work/calibre/src/calibre/library/database2.py:1551
msgid "