This commit is contained in:
Kovid Goyal 2009-04-08 20:06:51 -07:00
commit 00842debc3
22 changed files with 399 additions and 182 deletions

View File

@ -66,7 +66,9 @@ class HTMLPreProcessor(object):
# Remove non breaking spaces
(re.compile(ur'\u00a0'), lambda match : ' '),
# Have paragraphs show better
(re.compile(r'<br.*?>'), lambda match : '<p>'),
]
# Fix Book Designer markup

View File

@ -7,7 +7,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import sys, os, re, StringIO
from calibre.ebooks.metadata import MetaInformation, authors_to_string, get_parser
from calibre.ebooks.metadata import MetaInformation, authors_to_string
from calibre.ptempfile import TemporaryDirectory
from pyPdf import PdfFileReader, PdfFileWriter
import Image
@ -96,40 +96,3 @@ def get_cover(stream):
traceback.print_exc()
return data.getvalue()
def option_parser():
p = get_parser('pdf')
p.remove_option('--category')
p.remove_option('--comment')
p.add_option('--get-cover', default=False, action='store_true',
help=_('Extract the cover'))
return p
def main(args=sys.argv):
p = option_parser()
opts, args = p.parse_args(args)
with open(os.path.abspath(os.path.expanduser(args[1])), 'r+b') as stream:
mi = get_metadata(stream, extract_cover=opts.get_cover)
changed = False
if opts.title:
mi.title = opts.title
changed = True
if opts.authors:
mi.authors = opts.authors.split(',')
changed = True
if changed:
set_metadata(stream, mi)
print unicode(get_metadata(stream, extract_cover=False)).encode('utf-8')
if mi.cover_data[1] is not None:
cpath = os.path.splitext(os.path.basename(args[1]))[0] + '_cover.jpg'
with open(cpath, 'wb') as f:
f.write(mi.cover_data[1])
print 'Cover saved to', f.name
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -10,8 +10,7 @@ import os
from calibre.customize.conversion import InputFormatPlugin
from calibre.ebooks.pdf.pdftohtml import pdftohtml
from calibre.ebooks.metadata.opf import OPFCreator
from calibre.ebooks.metadata import MetaInformation
#from calibre.ebooks.metadata.meta import metadata_from_formats
from calibre.customize.builtins import PDFMetadataReader
class PDFInput(InputFormatPlugin):
@ -27,8 +26,7 @@ class PDFInput(InputFormatPlugin):
with open('index.html', 'wb') as index:
index.write(html)
#mi = metadata_from_formats([stream.name])
mi = MetaInformation(_('Unknown'), _('Unknown'))
mi = PDFMetadataReader(None).get_metadata(stream, 'pdf')
opf = OPFCreator(os.getcwd(), mi)
opf.create_manifest([('index.html', None)])
opf.create_spine(['index.html'])

View File

@ -15,10 +15,13 @@ from calibre.utils.config import OptionParser
from calibre.utils.logging import Log
from calibre.constants import preferred_encoding
from calibre.customize.conversion import OptionRecommendation
from calibre.ebooks.pdf.manipulate import crop, info, merge, reverse, split
from calibre.ebooks.pdf.manipulate import crop, decrypt, encrypt, \
info, merge, reverse, split
COMMANDS = {
'crop' : crop,
'decrypt' : decrypt,
'encrypt' : encrypt,
'info' : info,
'merge' : merge,
'reverse' : reverse,

View File

@ -25,7 +25,7 @@ from pyPdf import PdfFileWriter, PdfFileReader
DEFAULT_CROP = '10'
USAGE = '%prog %%name ' + _('''
USAGE = '\n%prog %%name ' + _('''\
[options] file.pdf
Crop a PDF file.
@ -132,7 +132,11 @@ def main(args=sys.argv, name=''):
return 1
if not is_valid_pdf(args[0]):
print 'Error: Could not read file `%s`. Is it a vaild PDF file or is it encrypted/DRMed?.' % args[0]
print 'Error: Could not read file `%s`.' % args[0]
return 1
if is_encrypted(args[0]):
print 'Error: file `%s` is encrypted.' % args[0]
return 1
mi = metadata_from_formats([args[0]])

View File

@ -0,0 +1,115 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
'''
Decrypt content of PDF.
'''
import os, sys
from optparse import OptionGroup, Option
from calibre.ebooks.metadata.meta import metadata_from_formats
from calibre.ebooks.metadata import authors_to_string
from calibre.utils.config import OptionParser
from calibre.utils.logging import Log
from calibre.constants import preferred_encoding
from calibre.customize.conversion import OptionRecommendation
from calibre.ebooks.pdf.verify import is_valid_pdf, is_encrypted
from pyPdf import PdfFileWriter, PdfFileReader
USAGE = '\n%prog %%name ' + _('''\
[options] file.pdf password
Decrypt a PDF.
''')
OPTIONS = set([
OptionRecommendation(name='output', recommended_value='decrypted.pdf',
level=OptionRecommendation.HIGH, long_switch='output', short_switch='o',
help=_('Path to output file. By default a file is created in the current directory.')),
])
class DecryptionError(Exception):
def __init__(self, pdf_path):
self.value = 'Unable to decrypt file `%s`.' % value
def __str__(self):
return repr(self.value)
def print_help(parser, log):
help = parser.format_help().encode(preferred_encoding, 'replace')
log(help)
def option_parser(name):
usage = USAGE.replace('%%name', name)
return OptionParser(usage=usage)
def option_recommendation_to_cli_option(add_option, rec):
opt = rec.option
switches = ['-'+opt.short_switch] if opt.short_switch else []
switches.append('--'+opt.long_switch)
attrs = dict(dest=opt.name, help=opt.help,
choices=opt.choices, default=rec.recommended_value)
add_option(Option(*switches, **attrs))
def add_options(parser):
group = OptionGroup(parser, _('Decrypt Options:'), _('Options to control the transformation of pdf'))
parser.add_option_group(group)
add_option = group.add_option
for rec in OPTIONS:
option_recommendation_to_cli_option(add_option, rec)
def decrypt(pdf_path, out_path, password):
pdf = PdfFileReader(open(os.path.abspath(pdf_path), 'rb'))
if pdf.decrypt(str(password)) == 0:
raise DecryptionError(pdf_path)
title = pdf.documentInfo.title if pdf.documentInfo.title else _('Unknown')
author = pdf.documentInfo.author if pdf.documentInfo.author else _('Unknown')
out_pdf = PdfFileWriter(title=title, author=author)
for page in pdf.pages:
out_pdf.addPage(page)
with open(out_path, 'wb') as out_file:
out_pdf.write(out_file)
def main(args=sys.argv, name=''):
log = Log()
parser = option_parser(name)
add_options(parser)
opts, args = parser.parse_args(args)
args = args[1:]
if len(args) < 2:
print 'Error: A PDF file and decryption password is required.\n'
print_help(parser, log)
return 1
if not is_valid_pdf(args[0]):
print 'Error: Could not read file `%s`.' % args[0]
return 1
if not is_encrypted(args[0]):
print 'Error: file `%s` is not encrypted.' % args[0]
return 1
try:
decrypt(args[0], opts.output, args[1])
except DecryptionError, e:
print e.value
return 1
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
'''
Encrypt a PDF.
'''
import os, sys
from optparse import OptionGroup, Option
from calibre.utils.config import OptionParser
from calibre.utils.logging import Log
from calibre.constants import preferred_encoding
from calibre.customize.conversion import OptionRecommendation
from calibre.ebooks.pdf.verify import is_valid_pdf, is_encrypted
from pyPdf import PdfFileWriter, PdfFileReader
USAGE = '\n%prog %%name ' + _('''\
[options] file.pdf password
Encrypt a PDF.
''')
OPTIONS = set([
OptionRecommendation(name='output', recommended_value='encrypted.pdf',
level=OptionRecommendation.HIGH, long_switch='output', short_switch='o',
help=_('Path to output file. By default a file is created in the current directory.')),
])
def print_help(parser, log):
help = parser.format_help().encode(preferred_encoding, 'replace')
log(help)
def option_parser(name):
usage = USAGE.replace('%%name', name)
return OptionParser(usage=usage)
def option_recommendation_to_cli_option(add_option, rec):
opt = rec.option
switches = ['-'+opt.short_switch] if opt.short_switch else []
switches.append('--'+opt.long_switch)
attrs = dict(dest=opt.name, help=opt.help,
choices=opt.choices, default=rec.recommended_value)
add_option(Option(*switches, **attrs))
def add_options(parser):
group = OptionGroup(parser, _('Encrypt Options:'), _('Options to control the transformation of pdf'))
parser.add_option_group(group)
add_option = group.add_option
for rec in OPTIONS:
option_recommendation_to_cli_option(add_option, rec)
def encrypt(pdf_path, out_path, password, metadata=None):
if metadata == None:
title = _('Unknown')
author = _('Unknown')
else:
title = metadata.title
author = authors_to_string(metadata.authors)
out_pdf = PdfFileWriter(title=title, author=author)
pdf = PdfFileReader(open(os.path.abspath(pdf_path), 'rb'))
for page in pdf.pages:
out_pdf.addPage(page)
with open(out_path, 'wb') as out_file:
out_pdf.encrypt(str(password))
out_pdf.write(out_file)
def main(args=sys.argv, name=''):
log = Log()
parser = option_parser(name)
add_options(parser)
opts, args = parser.parse_args(args)
args = args[1:]
if len(args) < 2:
print 'Error: A PDF file and decryption password is required.\n'
print_help(parser, log)
return 1
if not is_valid_pdf(args[0]):
print 'Error: Could not read file `%s`.' % args[0]
return 1
if is_encrypted(args[0]):
print 'Error: file `%s` is already encrypted.' % args[0]
return 1
mi = metadata_from_formats([args[0]])
encrypt(args[0], opts.output, args[1], mi)
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -16,11 +16,11 @@ from calibre.utils.config import OptionParser
from calibre.utils.logging import Log
from calibre.constants import preferred_encoding
from calibre.customize.conversion import OptionRecommendation
from calibre.ebooks.pdf.verify import is_valid_pdfs
from calibre.ebooks.pdf.verify import is_valid_pdfs, is_encrypted
from pyPdf import PdfFileWriter, PdfFileReader
USAGE = '%prog %%name ' + _('''
USAGE = '\n%prog %%name ' + _('''\
file.pdf ...
Get info about a PDF.
@ -72,9 +72,17 @@ def main(args=sys.argv, name=''):
bad_pdfs = is_valid_pdfs(args)
if bad_pdfs != []:
for pdf in bad_pdfs:
print 'Error: Could not read file `%s`. Is it a vaild PDF file or is it encrypted/DRMed?.' % pdf
print 'Error: Could not read file `%s`.' % pdf
return 1
enc = False
for pdf in args:
if is_encrypted(pdf):
enc = True
print 'Error: file `%s` is encrypted. Please decrypt first.' % pdf
if enc:
return 1
for pdf in args:
print_info(pdf)

View File

@ -22,7 +22,7 @@ from calibre.ebooks.pdf.verify import is_valid_pdfs
from pyPdf import PdfFileWriter, PdfFileReader
USAGE = '%prog %%name ' + _('''
USAGE = '\n%prog %%name ' + _('''\
[options] file1.pdf file2.pdf ...
Metadata will be used from the first PDF specified.
@ -94,9 +94,17 @@ def main(args=sys.argv, name=''):
bad_pdfs = is_valid_pdfs(args)
if bad_pdfs != []:
for pdf in bad_pdfs:
print 'Error: Could not read file `%s`. Is it a vaild PDF file or is it encrypted/DRMed?.' % pdf
print 'Error: Could not read file `%s`.' % pdf
return 1
enc = False
for pdf in args:
if is_encrypted(pdf):
enc = True
print 'Error: file `%s` is encrypted.' % pdf
if enc:
return 1
mi = metadata_from_formats([args[0]])
merge_files(args, opts.output, mi)

View File

@ -22,10 +22,10 @@ from calibre.ebooks.pdf.verify import is_valid_pdf
from pyPdf import PdfFileWriter, PdfFileReader
USAGE = '%prog %%name ' + _('''
USAGE = '\n%prog %%name ' + _('''\
[options] file.pdf
Reverse PDF.
Reverse a PDF.
''')
OPTIONS = set([
@ -89,7 +89,11 @@ def main(args=sys.argv, name=''):
return 1
if not is_valid_pdf(args[0]):
print 'Error: Could not read file `%s`. Is it a vaild PDF file or is it encrypted/DRMed?.' % args[0]
print 'Error: Could not read file `%s`.' % args[0]
return 1
if is_encrypted(args[0]):
print 'Error: file `%s` is encrypted.' % args[0]
return 1
mi = metadata_from_formats([args[0]])

View File

@ -185,7 +185,11 @@ def main(args=sys.argv, name=''):
return 1
if not is_valid_pdf(pdf):
print 'Error: Could not read file `%s`. Is it a vaild PDF file or is it encrypted/DRMed?.' % pdf
print 'Error: Could not read file `%s`.' % pdf
return 1
if is_encrypted(args[0]):
print 'Error: file `%s` is encrypted.' % args[0]
return 1
pages, page_ranges = clean_page_list(pdf, pages, page_ranges)

View File

@ -17,7 +17,7 @@ from calibre.customize.conversion import OutputFormatPlugin, \
OptionRecommendation
from calibre.ebooks.oeb.output import OEBOutput
from calibre.ptempfile import TemporaryDirectory
from calibre.ebooks.pdf.writer import PDFWriter
from calibre.ebooks.pdf.writer import PDFWriter, PDFMetadata
from calibre.ebooks.pdf.pageoptions import UNITS, unit, PAPER_SIZES, \
paper_size, ORIENTATIONS, orientation, PageOptions
@ -88,7 +88,7 @@ class PDFOutput(OutputFormatPlugin):
out_stream.seek(0)
out_stream.truncate()
writer.dump(opf, out_stream)
writer.dump(opf, out_stream, PDFMetadata(oeb_book.metadata))
if close:
out_stream.close()

View File

@ -6,7 +6,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>, ' \
'2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import errno, os, sys, subprocess
import errno, os, re, sys, subprocess
from functools import partial
from calibre.ebooks import ConversionError, DRMError

View File

@ -35,3 +35,10 @@ def is_valid_pdfs(pdf_paths):
if not is_valid_pdf(pdf_path):
invalid.append(pdf_path)
return invalid
def is_encrypted(pdf_path):
with open(os.path.abspath(pdf_path), 'rb') as pdf_file:
pdf = PdfFileReader(pdf_file)
if pdf.isEncrypted:
return True
return False

View File

@ -13,6 +13,7 @@ import os, shutil, sys
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.ebooks.pdf.pageoptions import PageOptions
from calibre.ebooks.metadata import authors_to_string
from calibre.ebooks.metadata.opf2 import OPF
from PyQt4 import QtCore
@ -22,6 +23,18 @@ from PyQt4.QtWebKit import QWebView
from pyPdf import PdfFileWriter, PdfFileReader
class PDFMetadata(object):
def __init__(self, oeb_metadata=None):
self.title = _('Unknown')
self.author = _('Unknown')
if oeb_metadata != None:
if len(oeb_metadata.title) >= 1:
self.title = oeb_metadata.title[0].value
if len(oeb_metadata.creator) >= 1:
self.author = authors_to_string([x.value for x in oeb_metadata.creator])
class PDFWriter(QObject):
def __init__(self, log, popts=PageOptions()):
if QApplication.instance() is None:
@ -37,8 +50,9 @@ class PDFWriter(QObject):
self.combine_queue = []
self.tmp_path = PersistentTemporaryDirectory('_any2pdf_parts')
self.popts = popts
def dump(self, opfpath, out_stream):
def dump(self, opfpath, out_stream, pdf_metadata):
self.metadata = pdf_metadata
self._delete_tmpdir()
opf = OPF(opfpath, os.path.dirname(opfpath))
@ -88,7 +102,7 @@ class PDFWriter(QObject):
self.logger.info('Combining individual PDF parts...')
try:
outPDF = PdfFileWriter()
outPDF = PdfFileWriter(title=self.metadata.title, author=self.metadata.author)
for item in self.combine_queue:
inputPDF = PdfFileReader(file(item, 'rb'))
for page in inputPDF.pages:

View File

@ -10,8 +10,7 @@ import os
from calibre.customize.conversion import InputFormatPlugin
from calibre.ebooks.markdown import markdown
from calibre.ebooks.metadata.opf import OPFCreator
from calibre.ebooks.metadata import MetaInformation
#from calibre.ebooks.metadata.meta import metadata_from_formats
from calibre.customize.builtins import TXTMetadataReader
class TXTInput(InputFormatPlugin):
@ -22,17 +21,19 @@ class TXTInput(InputFormatPlugin):
def convert(self, stream, options, file_ext, log,
accelerators):
txt = stream.read()
ienc = stream.encoding if stream.encoding else 'utf-8'
if options.input_encoding:
ienc = options.input_encoding
txt = stream.read().decode(ienc)
md = markdown.Markdown(
extensions=['footnotes', 'tables', 'toc'],
safe_mode=False,)
html = '<html><body>'+md.convert(txt)+'</body></html>'
html = '<html><head><title /></head><body>'+md.convert(txt)+'</body></html>'
with open('index.html', 'wb') as index:
index.write(html.encode('utf-8'))
#mi = metadata_from_formats([stream.name])
mi = MetaInformation(_('Unknown'), _('Unknown'))
mi = TXTMetadataReader(None).get_metadata(stream, 'txt')
opf = OPFCreator(os.getcwd(), mi)
opf.create_manifest([('index.html', None)])
opf.create_spine(['index.html'])

View File

@ -34,7 +34,7 @@ class TXTOutput(OutputFormatPlugin):
def convert(self, oeb_book, output_path, input_plugin, opts, log):
metadata = TxtMetadata()
if opts.prepend_metadata.lower() == 'true':
metadata.author = opts.authors if opts.authors else authors_to_string(oeb_book.metadata.authors.value) if oeb_book.metadata.authors != [] else _('Unknown')
metadata.author = opts.authors if opts.authors else authors_to_string([x.value for x in oeb_book.metadata.creator]) if oeb_book.metadata.creator != [] else _('Unknown')
metadata.title = opts.title if opts.title else oeb_book.metadata.title[0].value if oeb_book.metadata.title != [] else _('Unknown')
writer = TxtWriter(TxtNewlines(opts.newline).newline, log)

View File

@ -10,12 +10,14 @@ from binascii import unhexlify
from PyQt4.Qt import QMenu, QAction, QActionGroup, QIcon, SIGNAL, QPixmap, \
Qt
from calibre.customize.ui import available_input_formats, available_output_formats
from calibre.devices import devices
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
from calibre.parallel import Job
from calibre.devices.scanner import DeviceScanner
from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \
pixmap_to_data, warning_dialog
pixmap_to_data, warning_dialog, \
info_dialog
from calibre.ebooks.metadata import authors_to_string
from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog
from calibre.devices.interface import Device
@ -575,10 +577,21 @@ class DeviceGUI(object):
def sync_to_device(self, on_card, delete_from_library,
specific_format=None):
rows = self.library_view.selectionModel().selectedRows()
specific_format=None, send_rows=None, do_auto_convert=True):
rows = self.library_view.selectionModel().selectedRows() if send_rows is None else send_rows
if not self.device_manager or not rows or len(rows) == 0:
return
_files, _auto_rows = self.library_view.model().get_preferred_formats(rows,
self.device_manager.device_class.FORMATS,
paths=True, set_metadata=True,
specific_format=specific_format,
exclude_auto=do_auto_convert)
if do_auto_convert:
rows = list(set(rows).difference(_auto_rows))
else:
_auto_rows = []
ids = iter(self.library_view.model().id(r) for r in rows)
metadata = self.library_view.model().get_metadata(rows)
for mi in metadata:
@ -586,10 +599,7 @@ class DeviceGUI(object):
if cdata:
mi['cover'] = self.cover_to_thumbnail(cdata)
metadata = iter(metadata)
_files = self.library_view.model().get_preferred_formats(rows,
self.device_manager.device_class.FORMATS,
paths=True, set_metadata=True,
specific_format=specific_format)
files = [getattr(f, 'name', None) for f in _files]
bad, good, gf, names, remove_ids = [], [], [], [], []
for f in files:
@ -615,6 +625,35 @@ class DeviceGUI(object):
remove = remove_ids if delete_from_library else []
self.upload_books(gf, names, good, on_card, memory=(_files, remove))
self.status_bar.showMessage(_('Sending books to device.'), 5000)
auto = []
if _auto_rows != []:
for row in _auto_rows:
if specific_format == None:
formats = [f.lower() for f in self.library_view.model().db.formats(row).split(',')]
formats = formats if formats != None else []
if list(set(formats).intersection(available_input_formats())) != [] and list(set(self.device_manager.device_class.FORMATS).intersection(available_output_formats())) != []:
auto.append(row)
else:
bad.append(self.library_view.model().title(row))
else:
if specific_format in available_output_formats():
auto.append(row)
else:
bad.append(self.library_view.model().title(row))
if auto != []:
autos = [self.library_view.model().title(row) for row in auto]
autos = '\n'.join('<li>%s</li>'%(i,) for i in autos)
d = info_dialog(self, _('No suitable formats'),
_('Auto converting the following books before uploading to the device:<br><ul>%s</ul>')%(autos,))
for fmt in self.device_manager.device_class.FORMATS:
if fmt in list(set(self.device_manager.device_class.FORMATS).intersection(set(available_output_formats()))):
format = fmt
break
d.exec_()
self.auto_convert(_auto_rows, on_card, format)
if bad:
bad = '\n'.join('<li>%s</li>'%(i,) for i in bad)
d = warning_dialog(self, _('No suitable formats'),

View File

@ -420,7 +420,8 @@ class BooksModel(QAbstractTableModel):
def get_preferred_formats(self, rows, formats, paths=False,
set_metadata=False, specific_format=None):
set_metadata=False, specific_format=None,
exclude_auto=False):
ans = []
need_auto = []
if specific_format is not None:
@ -448,7 +449,8 @@ class BooksModel(QAbstractTableModel):
ans.append(pt)
else:
need_auto.append(row)
ans.append(None)
if not exclude_auto:
ans.append(None)
return ans, need_auto
def id(self, row):

View File

@ -969,18 +969,9 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
def auto_convert(self, rows, on_card, format):
previous = self.library_view.currentIndex()
comics, others = [], []
db = self.library_view.model().db
for r in rows:
formats = db.formats(r)
if not formats: continue
formats = formats.lower().split(',')
if 'cbr' in formats or 'cbz' in formats:
comics.append(r)
else:
others.append(r)
jobs, changed, bad_rows = auto_convert_ebook(format, self, self.library_view.model().db, comics, others)
jobs, changed, bad_rows = auto_convert_ebook(format, self, self.library_view.model().db, rows)
if jobs is None:
return
for func, args, desc, fmt, id, temp_files in jobs:
if id not in bad_rows:
job = self.job_manager.run_job(Dispatcher(self.book_auto_converted),
@ -1064,7 +1055,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
if job.exception is not None:
self.job_exception(job)
return
data = open(temp_files[-1].name, 'rb')
data = open(temp_files[0].name, 'rb')
self.library_view.model().db.add_format(book_id, fmt, data, index_is_id=True)
data.close()
self.status_bar.showMessage(job.description + (' completed'), 2000)
@ -1081,7 +1072,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.library_view.model().current_changed(current, QModelIndex())
r = self.library_view.model().index(self.library_view.model().db.row(book_id), 0)
self.sync_to_device(on_card, False, specific_format=fmt, send_rows=[r], auto_convert=False)
self.sync_to_device(on_card, False, specific_format=fmt, send_rows=[r], do_auto_convert=False)
def book_converted(self, job):
temp_files, fmt, book_id = self.conversion_jobs.pop(job)

View File

@ -9,6 +9,7 @@ Logic for setting up conversion jobs
import os
from PyQt4.Qt import QDialog
from calibre.customize.ui import available_input_formats
from calibre.utils.config import prefs
from calibre.gui2.dialogs.lrf_single import LRFSingleDialog, LRFBulkDialog
from calibre.gui2.dialogs.epub import Config as EPUBConvert
@ -22,6 +23,11 @@ from calibre.ebooks.epub.from_any import SOURCE_FORMATS as EPUB_PREFERRED_SOURCE
from calibre.ebooks.mobi.from_any import config as mobiconfig
from calibre.ebooks.lrf.comic.convert_from import config as comicconfig
# Ordered list of source formats. Items closer to the beginning are
# preferred for conversion over those toward the end.
PREFERRED_SOURCE_FORMATS = ['epub', 'lit', 'mobi', 'prc', 'azw', 'fb2', 'odt', 'rtf',
'txt', 'pdf', 'oebzip', 'htm', 'html']
def get_dialog(fmt):
return {
'epub':EPUBConvert,
@ -34,101 +40,48 @@ def get_config(fmt):
'mobi':mobiconfig,
}[fmt]
def auto_convert(fmt, parent, db, comics, others):
def auto_convert(fmt, parent, db, rows):
changed = False
jobs = []
total = sum(map(len, (others, comics)))
total = len(rows)
if total == 0:
return
return None, None, None
parent.status_bar.showMessage(_('Starting auto conversion of %d books')%total, 2000)
i = 0
bad_rows = []
for i, row in enumerate(others+comics):
for i, row in enumerate(rows):
row_id = db.id(row)
if row in others:
temp_files = []
data = None
for _fmt in EPUB_PREFERRED_SOURCE_FORMATS:
try:
data = db.format(row, _fmt.upper())
if data is not None:
break
except:
continue
if data is None:
bad_rows.append(row)
continue
temp_files = []
defaults = db.conversion_options(db.id(row), fmt)
defaults = defaults if defaults else ''
options = get_config(fmt)(defaults=defaults).parse()
mi = db.get_metadata(row)
opf = OPFCreator(os.getcwdu(), mi)
opf_file = PersistentTemporaryFile('.opf')
opf.render(opf_file)
opf_file.close()
pt = PersistentTemporaryFile('.'+_fmt.lower())
pt.write(data)
pt.close()
of = PersistentTemporaryFile('.'+fmt)
of.close()
cover = db.cover(row)
cf = None
if cover:
cf = PersistentTemporaryFile('.jpeg')
cf.write(cover)
cf.close()
options.cover = cf.name
options.output = of.name
options.from_opf = opf_file.name
args = [options, pt.name]
desc = _('Auto convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
temp_files = [cf] if cf is not None else []
temp_files.extend([opf_file, pt, of])
jobs.append(('any2'+fmt, args, desc, fmt.upper(), row_id, temp_files))
changed = True
else:
defaults = db.conversion_options(db.id(row), fmt)
defaults = defaults if defaults else ''
options = comicconfig(defaults=defaults).parse()
mi = db.get_metadata(row)
if mi.title:
options.title = mi.title
if mi.authors:
options.author = ','.join(mi.authors)
data = None
for _fmt in ['cbz', 'cbr']:
try:
data = db.format(row, _fmt.upper())
if data is not None:
break
except:
continue
if data is None:
data = None
in_formats = [f.lower() for f in db.formats(row).split(',')]
in_formats = list(set(in_formats).intersection(available_input_formats()))
for _fmt in PREFERRED_SOURCE_FORMATS:
if _fmt in in_formats:
data = _fmt
break
if data is None:
if in_formats != []:
data = list(in_formats)[0]
else:
bad_rows.append(row)
continue
pt = PersistentTemporaryFile('.'+_fmt.lower())
pt.write(data)
pt.close()
of = PersistentTemporaryFile('.'+fmt)
of.close()
setattr(options, 'output', of.name)
options.verbose = 1
args = [pt.name, options]
desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
jobs.append(('comic2'+fmt, args, desc, fmt.upper(), row_id, [pt, of]))
changed = True
mi = db.get_metadata(row)
in_file = db.format_abspath(row, data)
out_file = PersistentTemporaryFile('.'+fmt.lower())
out_file.write(data)
out_file.close()
desc = _('Auto convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
args = [['', in_file, out_file.name]]
temp_files = [out_file]
jobs.append(('ebook-convert', args, desc, fmt.upper(), row_id, temp_files))
changed = True
if bad_rows:
res = []
@ -141,9 +94,6 @@ def auto_convert(fmt, parent, db, comics, others):
return jobs, changed, bad_rows
def auto_convert_lrf(fmt, parent, db, comics, others):
pass
def convert_single(fmt, parent, db, comics, others):
changed = False
jobs = []
@ -505,11 +455,7 @@ def fetch_scheduled_recipe(recipe, script):
return 'feeds2'+fmt, [args], _('Fetch news from ')+recipe.title, fmt.upper(), [pt]
def auto_convert_ebook(*args):
fmt = args[0] if args[0] else 'epub'
if fmt == 'lrf':
return auto_convert_lrf()
elif fmt in ('epub', 'mobi'):
return auto_convert(*args)
return auto_convert(*args)
def convert_single_ebook(*args):
fmt = prefs['output_format'].lower()

View File

@ -79,6 +79,9 @@ PARALLEL_FUNCS = {
'comic2mobi' :
('calibre.ebooks.mobi.from_comic', 'convert', {}, 'notification'),
'ebook-convert' :
('calibre.ebooks.conversion.cli', 'main', {}, None),
}