mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
IGN:...
This commit is contained in:
commit
00842debc3
@ -66,7 +66,9 @@ class HTMLPreProcessor(object):
|
|||||||
|
|
||||||
# Remove non breaking spaces
|
# Remove non breaking spaces
|
||||||
(re.compile(ur'\u00a0'), lambda match : ' '),
|
(re.compile(ur'\u00a0'), lambda match : ' '),
|
||||||
|
|
||||||
|
# Have paragraphs show better
|
||||||
|
(re.compile(r'<br.*?>'), lambda match : '<p>'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Fix Book Designer markup
|
# Fix Book Designer markup
|
||||||
|
@ -7,7 +7,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
|
|
||||||
import sys, os, re, StringIO
|
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 calibre.ptempfile import TemporaryDirectory
|
||||||
from pyPdf import PdfFileReader, PdfFileWriter
|
from pyPdf import PdfFileReader, PdfFileWriter
|
||||||
import Image
|
import Image
|
||||||
@ -96,40 +96,3 @@ def get_cover(stream):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
return data.getvalue()
|
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())
|
|
||||||
|
@ -10,8 +10,7 @@ import os
|
|||||||
from calibre.customize.conversion import InputFormatPlugin
|
from calibre.customize.conversion import InputFormatPlugin
|
||||||
from calibre.ebooks.pdf.pdftohtml import pdftohtml
|
from calibre.ebooks.pdf.pdftohtml import pdftohtml
|
||||||
from calibre.ebooks.metadata.opf import OPFCreator
|
from calibre.ebooks.metadata.opf import OPFCreator
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.customize.builtins import PDFMetadataReader
|
||||||
#from calibre.ebooks.metadata.meta import metadata_from_formats
|
|
||||||
|
|
||||||
class PDFInput(InputFormatPlugin):
|
class PDFInput(InputFormatPlugin):
|
||||||
|
|
||||||
@ -27,8 +26,7 @@ class PDFInput(InputFormatPlugin):
|
|||||||
with open('index.html', 'wb') as index:
|
with open('index.html', 'wb') as index:
|
||||||
index.write(html)
|
index.write(html)
|
||||||
|
|
||||||
#mi = metadata_from_formats([stream.name])
|
mi = PDFMetadataReader(None).get_metadata(stream, 'pdf')
|
||||||
mi = MetaInformation(_('Unknown'), _('Unknown'))
|
|
||||||
opf = OPFCreator(os.getcwd(), mi)
|
opf = OPFCreator(os.getcwd(), mi)
|
||||||
opf.create_manifest([('index.html', None)])
|
opf.create_manifest([('index.html', None)])
|
||||||
opf.create_spine(['index.html'])
|
opf.create_spine(['index.html'])
|
||||||
|
@ -15,10 +15,13 @@ from calibre.utils.config import OptionParser
|
|||||||
from calibre.utils.logging import Log
|
from calibre.utils.logging import Log
|
||||||
from calibre.constants import preferred_encoding
|
from calibre.constants import preferred_encoding
|
||||||
from calibre.customize.conversion import OptionRecommendation
|
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 = {
|
COMMANDS = {
|
||||||
'crop' : crop,
|
'crop' : crop,
|
||||||
|
'decrypt' : decrypt,
|
||||||
|
'encrypt' : encrypt,
|
||||||
'info' : info,
|
'info' : info,
|
||||||
'merge' : merge,
|
'merge' : merge,
|
||||||
'reverse' : reverse,
|
'reverse' : reverse,
|
||||||
|
@ -25,7 +25,7 @@ from pyPdf import PdfFileWriter, PdfFileReader
|
|||||||
|
|
||||||
DEFAULT_CROP = '10'
|
DEFAULT_CROP = '10'
|
||||||
|
|
||||||
USAGE = '%prog %%name ' + _('''
|
USAGE = '\n%prog %%name ' + _('''\
|
||||||
[options] file.pdf
|
[options] file.pdf
|
||||||
|
|
||||||
Crop a PDF file.
|
Crop a PDF file.
|
||||||
@ -132,7 +132,11 @@ def main(args=sys.argv, name=''):
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
if not is_valid_pdf(args[0]):
|
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
|
return 1
|
||||||
|
|
||||||
mi = metadata_from_formats([args[0]])
|
mi = metadata_from_formats([args[0]])
|
||||||
|
115
src/calibre/ebooks/pdf/manipulate/decrypt.py
Normal file
115
src/calibre/ebooks/pdf/manipulate/decrypt.py
Normal 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())
|
105
src/calibre/ebooks/pdf/manipulate/encrypt.py
Normal file
105
src/calibre/ebooks/pdf/manipulate/encrypt.py
Normal 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())
|
@ -16,11 +16,11 @@ from calibre.utils.config import OptionParser
|
|||||||
from calibre.utils.logging import Log
|
from calibre.utils.logging import Log
|
||||||
from calibre.constants import preferred_encoding
|
from calibre.constants import preferred_encoding
|
||||||
from calibre.customize.conversion import OptionRecommendation
|
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
|
from pyPdf import PdfFileWriter, PdfFileReader
|
||||||
|
|
||||||
USAGE = '%prog %%name ' + _('''
|
USAGE = '\n%prog %%name ' + _('''\
|
||||||
file.pdf ...
|
file.pdf ...
|
||||||
|
|
||||||
Get info about a PDF.
|
Get info about a PDF.
|
||||||
@ -72,9 +72,17 @@ def main(args=sys.argv, name=''):
|
|||||||
bad_pdfs = is_valid_pdfs(args)
|
bad_pdfs = is_valid_pdfs(args)
|
||||||
if bad_pdfs != []:
|
if bad_pdfs != []:
|
||||||
for pdf in 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
|
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:
|
for pdf in args:
|
||||||
print_info(pdf)
|
print_info(pdf)
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ from calibre.ebooks.pdf.verify import is_valid_pdfs
|
|||||||
|
|
||||||
from pyPdf import PdfFileWriter, PdfFileReader
|
from pyPdf import PdfFileWriter, PdfFileReader
|
||||||
|
|
||||||
USAGE = '%prog %%name ' + _('''
|
USAGE = '\n%prog %%name ' + _('''\
|
||||||
[options] file1.pdf file2.pdf ...
|
[options] file1.pdf file2.pdf ...
|
||||||
|
|
||||||
Metadata will be used from the first PDF specified.
|
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)
|
bad_pdfs = is_valid_pdfs(args)
|
||||||
if bad_pdfs != []:
|
if bad_pdfs != []:
|
||||||
for pdf in 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
|
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]])
|
mi = metadata_from_formats([args[0]])
|
||||||
|
|
||||||
merge_files(args, opts.output, mi)
|
merge_files(args, opts.output, mi)
|
||||||
|
@ -22,10 +22,10 @@ from calibre.ebooks.pdf.verify import is_valid_pdf
|
|||||||
|
|
||||||
from pyPdf import PdfFileWriter, PdfFileReader
|
from pyPdf import PdfFileWriter, PdfFileReader
|
||||||
|
|
||||||
USAGE = '%prog %%name ' + _('''
|
USAGE = '\n%prog %%name ' + _('''\
|
||||||
[options] file.pdf
|
[options] file.pdf
|
||||||
|
|
||||||
Reverse PDF.
|
Reverse a PDF.
|
||||||
''')
|
''')
|
||||||
|
|
||||||
OPTIONS = set([
|
OPTIONS = set([
|
||||||
@ -89,7 +89,11 @@ def main(args=sys.argv, name=''):
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
if not is_valid_pdf(args[0]):
|
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
|
return 1
|
||||||
|
|
||||||
mi = metadata_from_formats([args[0]])
|
mi = metadata_from_formats([args[0]])
|
||||||
|
@ -185,7 +185,11 @@ def main(args=sys.argv, name=''):
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
if not is_valid_pdf(pdf):
|
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
|
return 1
|
||||||
|
|
||||||
pages, page_ranges = clean_page_list(pdf, pages, page_ranges)
|
pages, page_ranges = clean_page_list(pdf, pages, page_ranges)
|
||||||
|
@ -17,7 +17,7 @@ from calibre.customize.conversion import OutputFormatPlugin, \
|
|||||||
OptionRecommendation
|
OptionRecommendation
|
||||||
from calibre.ebooks.oeb.output import OEBOutput
|
from calibre.ebooks.oeb.output import OEBOutput
|
||||||
from calibre.ptempfile import TemporaryDirectory
|
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, \
|
from calibre.ebooks.pdf.pageoptions import UNITS, unit, PAPER_SIZES, \
|
||||||
paper_size, ORIENTATIONS, orientation, PageOptions
|
paper_size, ORIENTATIONS, orientation, PageOptions
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ class PDFOutput(OutputFormatPlugin):
|
|||||||
|
|
||||||
out_stream.seek(0)
|
out_stream.seek(0)
|
||||||
out_stream.truncate()
|
out_stream.truncate()
|
||||||
writer.dump(opf, out_stream)
|
writer.dump(opf, out_stream, PDFMetadata(oeb_book.metadata))
|
||||||
|
|
||||||
if close:
|
if close:
|
||||||
out_stream.close()
|
out_stream.close()
|
||||||
|
@ -6,7 +6,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>, ' \
|
|||||||
'2009, John Schember <john@nachtimwald.com>'
|
'2009, John Schember <john@nachtimwald.com>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import errno, os, sys, subprocess
|
import errno, os, re, sys, subprocess
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from calibre.ebooks import ConversionError, DRMError
|
from calibre.ebooks import ConversionError, DRMError
|
||||||
|
@ -35,3 +35,10 @@ def is_valid_pdfs(pdf_paths):
|
|||||||
if not is_valid_pdf(pdf_path):
|
if not is_valid_pdf(pdf_path):
|
||||||
invalid.append(pdf_path)
|
invalid.append(pdf_path)
|
||||||
return invalid
|
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
|
||||||
|
@ -13,6 +13,7 @@ import os, shutil, sys
|
|||||||
|
|
||||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
from calibre.ptempfile import PersistentTemporaryDirectory
|
||||||
from calibre.ebooks.pdf.pageoptions import PageOptions
|
from calibre.ebooks.pdf.pageoptions import PageOptions
|
||||||
|
from calibre.ebooks.metadata import authors_to_string
|
||||||
from calibre.ebooks.metadata.opf2 import OPF
|
from calibre.ebooks.metadata.opf2 import OPF
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
@ -22,6 +23,18 @@ from PyQt4.QtWebKit import QWebView
|
|||||||
|
|
||||||
from pyPdf import PdfFileWriter, PdfFileReader
|
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):
|
class PDFWriter(QObject):
|
||||||
def __init__(self, log, popts=PageOptions()):
|
def __init__(self, log, popts=PageOptions()):
|
||||||
if QApplication.instance() is None:
|
if QApplication.instance() is None:
|
||||||
@ -37,8 +50,9 @@ class PDFWriter(QObject):
|
|||||||
self.combine_queue = []
|
self.combine_queue = []
|
||||||
self.tmp_path = PersistentTemporaryDirectory('_any2pdf_parts')
|
self.tmp_path = PersistentTemporaryDirectory('_any2pdf_parts')
|
||||||
self.popts = popts
|
self.popts = popts
|
||||||
|
|
||||||
def dump(self, opfpath, out_stream):
|
def dump(self, opfpath, out_stream, pdf_metadata):
|
||||||
|
self.metadata = pdf_metadata
|
||||||
self._delete_tmpdir()
|
self._delete_tmpdir()
|
||||||
|
|
||||||
opf = OPF(opfpath, os.path.dirname(opfpath))
|
opf = OPF(opfpath, os.path.dirname(opfpath))
|
||||||
@ -88,7 +102,7 @@ class PDFWriter(QObject):
|
|||||||
self.logger.info('Combining individual PDF parts...')
|
self.logger.info('Combining individual PDF parts...')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
outPDF = PdfFileWriter()
|
outPDF = PdfFileWriter(title=self.metadata.title, author=self.metadata.author)
|
||||||
for item in self.combine_queue:
|
for item in self.combine_queue:
|
||||||
inputPDF = PdfFileReader(file(item, 'rb'))
|
inputPDF = PdfFileReader(file(item, 'rb'))
|
||||||
for page in inputPDF.pages:
|
for page in inputPDF.pages:
|
||||||
|
@ -10,8 +10,7 @@ import os
|
|||||||
from calibre.customize.conversion import InputFormatPlugin
|
from calibre.customize.conversion import InputFormatPlugin
|
||||||
from calibre.ebooks.markdown import markdown
|
from calibre.ebooks.markdown import markdown
|
||||||
from calibre.ebooks.metadata.opf import OPFCreator
|
from calibre.ebooks.metadata.opf import OPFCreator
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.customize.builtins import TXTMetadataReader
|
||||||
#from calibre.ebooks.metadata.meta import metadata_from_formats
|
|
||||||
|
|
||||||
class TXTInput(InputFormatPlugin):
|
class TXTInput(InputFormatPlugin):
|
||||||
|
|
||||||
@ -22,17 +21,19 @@ class TXTInput(InputFormatPlugin):
|
|||||||
|
|
||||||
def convert(self, stream, options, file_ext, log,
|
def convert(self, stream, options, file_ext, log,
|
||||||
accelerators):
|
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(
|
md = markdown.Markdown(
|
||||||
extensions=['footnotes', 'tables', 'toc'],
|
extensions=['footnotes', 'tables', 'toc'],
|
||||||
safe_mode=False,)
|
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:
|
with open('index.html', 'wb') as index:
|
||||||
index.write(html.encode('utf-8'))
|
index.write(html.encode('utf-8'))
|
||||||
|
|
||||||
#mi = metadata_from_formats([stream.name])
|
mi = TXTMetadataReader(None).get_metadata(stream, 'txt')
|
||||||
mi = MetaInformation(_('Unknown'), _('Unknown'))
|
|
||||||
opf = OPFCreator(os.getcwd(), mi)
|
opf = OPFCreator(os.getcwd(), mi)
|
||||||
opf.create_manifest([('index.html', None)])
|
opf.create_manifest([('index.html', None)])
|
||||||
opf.create_spine(['index.html'])
|
opf.create_spine(['index.html'])
|
||||||
|
@ -34,7 +34,7 @@ class TXTOutput(OutputFormatPlugin):
|
|||||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||||
metadata = TxtMetadata()
|
metadata = TxtMetadata()
|
||||||
if opts.prepend_metadata.lower() == 'true':
|
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')
|
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)
|
writer = TxtWriter(TxtNewlines(opts.newline).newline, log)
|
||||||
|
@ -10,12 +10,14 @@ from binascii import unhexlify
|
|||||||
from PyQt4.Qt import QMenu, QAction, QActionGroup, QIcon, SIGNAL, QPixmap, \
|
from PyQt4.Qt import QMenu, QAction, QActionGroup, QIcon, SIGNAL, QPixmap, \
|
||||||
Qt
|
Qt
|
||||||
|
|
||||||
|
from calibre.customize.ui import available_input_formats, available_output_formats
|
||||||
from calibre.devices import devices
|
from calibre.devices import devices
|
||||||
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
||||||
from calibre.parallel import Job
|
from calibre.parallel import Job
|
||||||
from calibre.devices.scanner import DeviceScanner
|
from calibre.devices.scanner import DeviceScanner
|
||||||
from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \
|
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.ebooks.metadata import authors_to_string
|
||||||
from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog
|
from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog
|
||||||
from calibre.devices.interface import Device
|
from calibre.devices.interface import Device
|
||||||
@ -575,10 +577,21 @@ class DeviceGUI(object):
|
|||||||
|
|
||||||
|
|
||||||
def sync_to_device(self, on_card, delete_from_library,
|
def sync_to_device(self, on_card, delete_from_library,
|
||||||
specific_format=None):
|
specific_format=None, send_rows=None, do_auto_convert=True):
|
||||||
rows = self.library_view.selectionModel().selectedRows()
|
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:
|
if not self.device_manager or not rows or len(rows) == 0:
|
||||||
return
|
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)
|
ids = iter(self.library_view.model().id(r) for r in rows)
|
||||||
metadata = self.library_view.model().get_metadata(rows)
|
metadata = self.library_view.model().get_metadata(rows)
|
||||||
for mi in metadata:
|
for mi in metadata:
|
||||||
@ -586,10 +599,7 @@ class DeviceGUI(object):
|
|||||||
if cdata:
|
if cdata:
|
||||||
mi['cover'] = self.cover_to_thumbnail(cdata)
|
mi['cover'] = self.cover_to_thumbnail(cdata)
|
||||||
metadata = iter(metadata)
|
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]
|
files = [getattr(f, 'name', None) for f in _files]
|
||||||
bad, good, gf, names, remove_ids = [], [], [], [], []
|
bad, good, gf, names, remove_ids = [], [], [], [], []
|
||||||
for f in files:
|
for f in files:
|
||||||
@ -615,6 +625,35 @@ class DeviceGUI(object):
|
|||||||
remove = remove_ids if delete_from_library else []
|
remove = remove_ids if delete_from_library else []
|
||||||
self.upload_books(gf, names, good, on_card, memory=(_files, remove))
|
self.upload_books(gf, names, good, on_card, memory=(_files, remove))
|
||||||
self.status_bar.showMessage(_('Sending books to device.'), 5000)
|
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:
|
if bad:
|
||||||
bad = '\n'.join('<li>%s</li>'%(i,) for i in bad)
|
bad = '\n'.join('<li>%s</li>'%(i,) for i in bad)
|
||||||
d = warning_dialog(self, _('No suitable formats'),
|
d = warning_dialog(self, _('No suitable formats'),
|
||||||
|
@ -420,7 +420,8 @@ class BooksModel(QAbstractTableModel):
|
|||||||
|
|
||||||
|
|
||||||
def get_preferred_formats(self, rows, formats, paths=False,
|
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 = []
|
ans = []
|
||||||
need_auto = []
|
need_auto = []
|
||||||
if specific_format is not None:
|
if specific_format is not None:
|
||||||
@ -448,7 +449,8 @@ class BooksModel(QAbstractTableModel):
|
|||||||
ans.append(pt)
|
ans.append(pt)
|
||||||
else:
|
else:
|
||||||
need_auto.append(row)
|
need_auto.append(row)
|
||||||
ans.append(None)
|
if not exclude_auto:
|
||||||
|
ans.append(None)
|
||||||
return ans, need_auto
|
return ans, need_auto
|
||||||
|
|
||||||
def id(self, row):
|
def id(self, row):
|
||||||
|
@ -969,18 +969,9 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
def auto_convert(self, rows, on_card, format):
|
def auto_convert(self, rows, on_card, format):
|
||||||
previous = self.library_view.currentIndex()
|
previous = self.library_view.currentIndex()
|
||||||
|
|
||||||
comics, others = [], []
|
jobs, changed, bad_rows = auto_convert_ebook(format, self, self.library_view.model().db, rows)
|
||||||
db = self.library_view.model().db
|
if jobs is None:
|
||||||
for r in rows:
|
return
|
||||||
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)
|
|
||||||
for func, args, desc, fmt, id, temp_files in jobs:
|
for func, args, desc, fmt, id, temp_files in jobs:
|
||||||
if id not in bad_rows:
|
if id not in bad_rows:
|
||||||
job = self.job_manager.run_job(Dispatcher(self.book_auto_converted),
|
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:
|
if job.exception is not None:
|
||||||
self.job_exception(job)
|
self.job_exception(job)
|
||||||
return
|
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)
|
self.library_view.model().db.add_format(book_id, fmt, data, index_is_id=True)
|
||||||
data.close()
|
data.close()
|
||||||
self.status_bar.showMessage(job.description + (' completed'), 2000)
|
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())
|
self.library_view.model().current_changed(current, QModelIndex())
|
||||||
|
|
||||||
r = self.library_view.model().index(self.library_view.model().db.row(book_id), 0)
|
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):
|
def book_converted(self, job):
|
||||||
temp_files, fmt, book_id = self.conversion_jobs.pop(job)
|
temp_files, fmt, book_id = self.conversion_jobs.pop(job)
|
||||||
|
@ -9,6 +9,7 @@ Logic for setting up conversion jobs
|
|||||||
import os
|
import os
|
||||||
from PyQt4.Qt import QDialog
|
from PyQt4.Qt import QDialog
|
||||||
|
|
||||||
|
from calibre.customize.ui import available_input_formats
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs
|
||||||
from calibre.gui2.dialogs.lrf_single import LRFSingleDialog, LRFBulkDialog
|
from calibre.gui2.dialogs.lrf_single import LRFSingleDialog, LRFBulkDialog
|
||||||
from calibre.gui2.dialogs.epub import Config as EPUBConvert
|
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.mobi.from_any import config as mobiconfig
|
||||||
from calibre.ebooks.lrf.comic.convert_from import config as comicconfig
|
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):
|
def get_dialog(fmt):
|
||||||
return {
|
return {
|
||||||
'epub':EPUBConvert,
|
'epub':EPUBConvert,
|
||||||
@ -34,101 +40,48 @@ def get_config(fmt):
|
|||||||
'mobi':mobiconfig,
|
'mobi':mobiconfig,
|
||||||
}[fmt]
|
}[fmt]
|
||||||
|
|
||||||
def auto_convert(fmt, parent, db, comics, others):
|
def auto_convert(fmt, parent, db, rows):
|
||||||
changed = False
|
changed = False
|
||||||
jobs = []
|
jobs = []
|
||||||
|
|
||||||
total = sum(map(len, (others, comics)))
|
total = len(rows)
|
||||||
if total == 0:
|
if total == 0:
|
||||||
return
|
return None, None, None
|
||||||
parent.status_bar.showMessage(_('Starting auto conversion of %d books')%total, 2000)
|
parent.status_bar.showMessage(_('Starting auto conversion of %d books')%total, 2000)
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
bad_rows = []
|
bad_rows = []
|
||||||
|
|
||||||
for i, row in enumerate(others+comics):
|
for i, row in enumerate(rows):
|
||||||
row_id = db.id(row)
|
row_id = db.id(row)
|
||||||
|
|
||||||
if row in others:
|
temp_files = []
|
||||||
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
|
|
||||||
|
|
||||||
defaults = db.conversion_options(db.id(row), fmt)
|
data = None
|
||||||
defaults = defaults if defaults else ''
|
in_formats = [f.lower() for f in db.formats(row).split(',')]
|
||||||
options = get_config(fmt)(defaults=defaults).parse()
|
in_formats = list(set(in_formats).intersection(available_input_formats()))
|
||||||
|
for _fmt in PREFERRED_SOURCE_FORMATS:
|
||||||
mi = db.get_metadata(row)
|
if _fmt in in_formats:
|
||||||
opf = OPFCreator(os.getcwdu(), mi)
|
data = _fmt
|
||||||
opf_file = PersistentTemporaryFile('.opf')
|
break
|
||||||
opf.render(opf_file)
|
if data is None:
|
||||||
opf_file.close()
|
if in_formats != []:
|
||||||
pt = PersistentTemporaryFile('.'+_fmt.lower())
|
data = list(in_formats)[0]
|
||||||
pt.write(data)
|
else:
|
||||||
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:
|
|
||||||
bad_rows.append(row)
|
bad_rows.append(row)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
pt = PersistentTemporaryFile('.'+_fmt.lower())
|
mi = db.get_metadata(row)
|
||||||
pt.write(data)
|
in_file = db.format_abspath(row, data)
|
||||||
pt.close()
|
out_file = PersistentTemporaryFile('.'+fmt.lower())
|
||||||
of = PersistentTemporaryFile('.'+fmt)
|
out_file.write(data)
|
||||||
of.close()
|
out_file.close()
|
||||||
setattr(options, 'output', of.name)
|
desc = _('Auto convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
|
||||||
options.verbose = 1
|
args = [['', in_file, out_file.name]]
|
||||||
args = [pt.name, options]
|
temp_files = [out_file]
|
||||||
desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
|
jobs.append(('ebook-convert', args, desc, fmt.upper(), row_id, temp_files))
|
||||||
jobs.append(('comic2'+fmt, args, desc, fmt.upper(), row_id, [pt, of]))
|
|
||||||
|
changed = True
|
||||||
changed = True
|
|
||||||
|
|
||||||
if bad_rows:
|
if bad_rows:
|
||||||
res = []
|
res = []
|
||||||
@ -141,9 +94,6 @@ def auto_convert(fmt, parent, db, comics, others):
|
|||||||
|
|
||||||
return jobs, changed, bad_rows
|
return jobs, changed, bad_rows
|
||||||
|
|
||||||
def auto_convert_lrf(fmt, parent, db, comics, others):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def convert_single(fmt, parent, db, comics, others):
|
def convert_single(fmt, parent, db, comics, others):
|
||||||
changed = False
|
changed = False
|
||||||
jobs = []
|
jobs = []
|
||||||
@ -505,11 +455,7 @@ def fetch_scheduled_recipe(recipe, script):
|
|||||||
return 'feeds2'+fmt, [args], _('Fetch news from ')+recipe.title, fmt.upper(), [pt]
|
return 'feeds2'+fmt, [args], _('Fetch news from ')+recipe.title, fmt.upper(), [pt]
|
||||||
|
|
||||||
def auto_convert_ebook(*args):
|
def auto_convert_ebook(*args):
|
||||||
fmt = args[0] if args[0] else 'epub'
|
return auto_convert(*args)
|
||||||
if fmt == 'lrf':
|
|
||||||
return auto_convert_lrf()
|
|
||||||
elif fmt in ('epub', 'mobi'):
|
|
||||||
return auto_convert(*args)
|
|
||||||
|
|
||||||
def convert_single_ebook(*args):
|
def convert_single_ebook(*args):
|
||||||
fmt = prefs['output_format'].lower()
|
fmt = prefs['output_format'].lower()
|
||||||
|
@ -79,6 +79,9 @@ PARALLEL_FUNCS = {
|
|||||||
|
|
||||||
'comic2mobi' :
|
'comic2mobi' :
|
||||||
('calibre.ebooks.mobi.from_comic', 'convert', {}, 'notification'),
|
('calibre.ebooks.mobi.from_comic', 'convert', {}, 'notification'),
|
||||||
|
|
||||||
|
'ebook-convert' :
|
||||||
|
('calibre.ebooks.conversion.cli', 'main', {}, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user