mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
Pull from driver-dev
This commit is contained in:
commit
43199d9dd2
@ -221,5 +221,4 @@ class MetadataWriterPlugin(Plugin):
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -295,9 +295,19 @@ from calibre.ebooks.pdf.output import PDFOutput
|
||||
from calibre.ebooks.pdb.ereader.output import EREADEROutput
|
||||
from calibre.customize.profiles import input_profiles, output_profiles
|
||||
|
||||
from calibre.devices.prs500.driver import PRS500
|
||||
from calibre.devices.prs505.driver import PRS505
|
||||
from calibre.devices.prs700.driver import PRS700
|
||||
from calibre.devices.cybookg3.driver import CYBOOKG3
|
||||
from calibre.devices.kindle.driver import KINDLE
|
||||
from calibre.devices.kindle.driver import KINDLE2
|
||||
from calibre.devices.blackberry.driver import BLACKBERRY
|
||||
from calibre.devices.eb600.driver import EB600
|
||||
|
||||
plugins = [HTML2ZIP, EPUBInput, MOBIInput, PDBInput, PDFInput, HTMLInput,
|
||||
TXTInput, OEBOutput, TXTOutput, PDFOutput, LITInput, ComicInput,
|
||||
FB2Input, ODTInput, RTFInput, EPUBOutput, EREADEROutput, RecipeInput]
|
||||
plugins += [PRS505, PRS700, CYBOOKG3, KINDLE, KINDLE2, BLACKBERRY, EB600]
|
||||
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
|
||||
x.__name__.endswith('MetadataReader')]
|
||||
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
|
||||
|
@ -10,6 +10,7 @@ from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin
|
||||
from calibre.customize.profiles import InputProfile, OutputProfile
|
||||
from calibre.customize.builtins import plugins as builtin_plugins
|
||||
from calibre.constants import __version__, iswindows, isosx
|
||||
from calibre.devices.interface import DevicePlugin
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
from calibre.utils.config import make_config_dir, Config, ConfigProxy, \
|
||||
plugin_dir, OptionParser
|
||||
@ -286,6 +287,12 @@ def available_output_formats():
|
||||
formats.add(plugin.file_type)
|
||||
return formats
|
||||
|
||||
def device_plugins():
|
||||
for plugin in _initialized_plugins:
|
||||
if isinstance(plugin, DevicePlugin):
|
||||
if not is_disabled(plugin):
|
||||
yield plugin
|
||||
|
||||
def disable_plugin(plugin_or_name):
|
||||
x = getattr(plugin_or_name, 'name', plugin_or_name)
|
||||
plugin = find_plugin(x)
|
||||
|
@ -5,19 +5,6 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
Device drivers.
|
||||
'''
|
||||
|
||||
def devices():
|
||||
from calibre.devices.prs500.driver import PRS500
|
||||
from calibre.devices.prs505.driver import PRS505
|
||||
from calibre.devices.prs700.driver import PRS700
|
||||
from calibre.devices.cybookg3.driver import CYBOOKG3
|
||||
from calibre.devices.kindle.driver import KINDLE
|
||||
from calibre.devices.kindle.driver import KINDLE2
|
||||
from calibre.devices.blackberry.driver import BLACKBERRY
|
||||
from calibre.devices.eb600.driver import EB600
|
||||
from calibre.devices.jetbook.driver import JETBOOK
|
||||
return (PRS500, PRS505, PRS700, CYBOOKG3, KINDLE, KINDLE2,
|
||||
BLACKBERRY, EB600, JETBOOK)
|
||||
|
||||
import time
|
||||
|
||||
DAY_MAP = dict(Sun=0, Mon=1, Tue=2, Wed=3, Thu=4, Fri=5, Sat=6)
|
||||
|
@ -7,6 +7,12 @@ __docformat__ = 'restructuredtext en'
|
||||
from calibre.devices.usbms.driver import USBMS
|
||||
|
||||
class BLACKBERRY(USBMS):
|
||||
|
||||
name = 'Blackberry Device Interface'
|
||||
description = _('Communicate with the Blackberry smart phone.')
|
||||
author = _('Kovid Goyal')
|
||||
supported_platforms = ['windows', 'linux']
|
||||
|
||||
# Ordered list of supported formats
|
||||
FORMATS = ['mobi', 'prc']
|
||||
|
||||
@ -16,15 +22,11 @@ class BLACKBERRY(USBMS):
|
||||
|
||||
VENDOR_NAME = 'RIM'
|
||||
WINDOWS_MAIN_MEM = 'BLACKBERRY_SD'
|
||||
#WINDOWS_CARD_MEM = 'CARD_STORAGE'
|
||||
|
||||
#OSX_MAIN_MEM = 'Kindle Internal Storage Media'
|
||||
#OSX_CARD_MEM = 'Kindle Card Storage Media'
|
||||
|
||||
MAIN_MEMORY_VOLUME_LABEL = 'Blackberry Main Memory'
|
||||
#STORAGE_CARD_VOLUME_LABEL = 'Kindle Storage Card'
|
||||
|
||||
EBOOK_DIR_MAIN = 'ebooks'
|
||||
#EBOOK_DIR_CARD = "documents"
|
||||
SUPPORTS_SUB_DIRS = True
|
||||
|
||||
|
@ -12,6 +12,12 @@ from calibre.devices.usbms.driver import USBMS
|
||||
import calibre.devices.cybookg3.t2b as t2b
|
||||
|
||||
class CYBOOKG3(USBMS):
|
||||
name = 'Cybook Gen 3 Device Interface'
|
||||
description = _('Communicate with the Cybook eBook reader.')
|
||||
author = _('John Schember')
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
|
||||
|
||||
# Ordered list of supported formats
|
||||
# Be sure these have an entry in calibre.devices.mime
|
||||
FORMATS = ['mobi', 'prc', 'html', 'pdf', 'rtf', 'txt']
|
||||
|
@ -7,6 +7,11 @@ Device driver for the Netronix EB600
|
||||
from calibre.devices.usbms.driver import USBMS
|
||||
|
||||
class EB600(USBMS):
|
||||
name = 'Netronix EB600 Device Interface'
|
||||
description = _('Communicate with the EB600 eBook reader.')
|
||||
author = _('Kovid Goyal')
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
|
||||
# Ordered list of supported formats
|
||||
FORMATS = ['epub', 'prc', 'chm', 'djvu', 'html', 'rtf', 'txt', 'pdf']
|
||||
DRM_FORMATS = ['prc', 'mobi', 'html', 'pdf', 'txt']
|
||||
|
@ -6,8 +6,9 @@ the GUI. A device backend must subclass the L{Device} class. See prs500.py for
|
||||
a backend that implement the Device interface for the SONY PRS500 Reader.
|
||||
"""
|
||||
|
||||
from calibre.customize import Plugin
|
||||
|
||||
class Device(object):
|
||||
class DevicePlugin(Plugin):
|
||||
"""
|
||||
Defines the interface that should be implemented by backends that
|
||||
communicate with an ebook reader.
|
||||
@ -16,6 +17,8 @@ class Device(object):
|
||||
the front-end needs to call several methods one after another, in which case
|
||||
the USB session should not be closed after each method call.
|
||||
"""
|
||||
type = _('Device Interface')
|
||||
|
||||
# Ordered list of supported formats
|
||||
FORMATS = ["lrf", "rtf", "pdf", "txt"]
|
||||
VENDOR_ID = 0x0000
|
||||
@ -27,8 +30,8 @@ class Device(object):
|
||||
# Whether the metadata on books can be set via the GUI.
|
||||
CAN_SET_METADATA = True
|
||||
|
||||
def __init__(self, key='-1', log_packets=False, report_progress=None) :
|
||||
"""
|
||||
def reset(self, key='-1', log_packets=False, report_progress=None) :
|
||||
"""
|
||||
@param key: The key to unlock the device
|
||||
@param log_packets: If true the packet stream to/from the device is logged
|
||||
@param report_progress: Function that is called with a % progress
|
||||
|
@ -11,6 +11,12 @@ from calibre.devices.usbms.driver import USBMS, metadata_from_formats
|
||||
from calibre import sanitize_file_name as sanitize
|
||||
|
||||
class JETBOOK(USBMS):
|
||||
name = 'Ectaco JetBook Device Interface'
|
||||
description = _('Communicate with the JetBook eBook reader.')
|
||||
author = _('James Ralston')
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
|
||||
|
||||
# Ordered list of supported formats
|
||||
# Be sure these have an entry in calibre.devices.mime
|
||||
FORMATS = ['epub', 'mobi', 'prc', 'txt', 'rtf', 'pdf']
|
||||
|
@ -6,9 +6,14 @@ Device driver for Amazon's Kindle
|
||||
|
||||
import os, re, sys
|
||||
|
||||
from calibre.devices.usbms.driver import USBMS, metadata_from_formats
|
||||
from calibre.devices.usbms.driver import USBMS
|
||||
|
||||
class KINDLE(USBMS):
|
||||
name = 'Kindle Device Interface'
|
||||
description = _('Communicate with the Kindle eBook reader.')
|
||||
author = _('John Schember')
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
|
||||
# Ordered list of supported formats
|
||||
FORMATS = ['azw', 'mobi', 'prc', 'azw1', 'tpz', 'txt']
|
||||
|
||||
@ -46,6 +51,7 @@ class KINDLE(USBMS):
|
||||
|
||||
@classmethod
|
||||
def metadata_from_path(cls, path):
|
||||
from calibre.devices.usbms.driver import metadata_from_formats
|
||||
mi = metadata_from_formats([path])
|
||||
if mi.title == _('Unknown') or ('-asin' in mi.title and '-type' in mi.title):
|
||||
match = cls.WIRELESS_FILE_NAME_PATTERN.match(os.path.basename(path))
|
||||
@ -58,6 +64,10 @@ class KINDLE(USBMS):
|
||||
|
||||
|
||||
class KINDLE2(KINDLE):
|
||||
name = 'Kindle 2 Device Interface'
|
||||
description = _('Communicate with the Kindle 2 eBook reader.')
|
||||
author = _('John Schember')
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
|
||||
PRODUCT_ID = [0x0002]
|
||||
BCD = [0x0100]
|
||||
|
@ -40,7 +40,7 @@ from array import array
|
||||
from functools import wraps
|
||||
from StringIO import StringIO
|
||||
|
||||
from calibre.devices.interface import Device
|
||||
from calibre.devices.interface import DevicePlugin
|
||||
from calibre.devices.libusb import Error as USBError
|
||||
from calibre.devices.libusb import get_device_by_id
|
||||
from calibre.devices.prs500.prstypes import *
|
||||
@ -76,12 +76,16 @@ class File(object):
|
||||
return self.name
|
||||
|
||||
|
||||
class PRS500(Device):
|
||||
class PRS500(DevicePlugin):
|
||||
|
||||
"""
|
||||
Implements the backend for communication with the SONY Reader.
|
||||
Each method decorated by C{safe} performs a task.
|
||||
"""
|
||||
name = 'PRS-500 Device Interface'
|
||||
description = _('Communicate with the Sony PRS-500 eBook reader.')
|
||||
author = _('Kovid Goyal')
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
|
||||
VENDOR_ID = 0x054c #: SONY Vendor Id
|
||||
PRODUCT_ID = 0x029b #: Product Id for the PRS-500
|
||||
@ -181,7 +185,7 @@ class PRS500(Device):
|
||||
|
||||
return run_session
|
||||
|
||||
def __init__(self, key='-1', log_packets=False, report_progress=None) :
|
||||
def reset(self, key='-1', log_packets=False, report_progress=None) :
|
||||
"""
|
||||
@param key: The key to unlock the device
|
||||
@param log_packets: If true the packet stream to/from the device is logged
|
||||
|
@ -1,5 +1,6 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net> ' \
|
||||
'2009, John Schember <john at nachtimwald.com>'
|
||||
'''
|
||||
Device driver for the SONY PRS-505
|
||||
'''
|
||||
@ -14,6 +15,12 @@ from calibre import iswindows, islinux, isosx, __appname__
|
||||
from calibre.devices.errors import PathError
|
||||
|
||||
class PRS505(CLI, Device):
|
||||
|
||||
name = 'PRS-505 Device Interface'
|
||||
description = _('Communicate with the Sony PRS-505 eBook reader.')
|
||||
author = _('Kovid Goyal and John Schember')
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
|
||||
FORMATS = ['epub', 'lrf', 'lrx', 'rtf', 'pdf', 'txt']
|
||||
|
||||
VENDOR_ID = [0x054c] #: SONY Vendor Id
|
||||
|
@ -8,6 +8,11 @@ Device driver for the SONY PRS-700
|
||||
from calibre.devices.prs505.driver import PRS505
|
||||
|
||||
class PRS700(PRS505):
|
||||
|
||||
name = 'PRS-700 Device Interface'
|
||||
description = _('Communicate with the Sony PRS-700 eBook reader.')
|
||||
author = _('Kovid Goyal and John Schember')
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
|
||||
BCD = [0x31a]
|
||||
|
||||
|
@ -8,11 +8,11 @@ device. This class handles device detection.
|
||||
|
||||
import os, subprocess, time, re
|
||||
|
||||
from calibre.devices.interface import Device as _Device
|
||||
from calibre.devices.interface import DevicePlugin as Device
|
||||
from calibre.devices.errors import DeviceError
|
||||
from calibre import iswindows, islinux, isosx, __appname__
|
||||
|
||||
class Device(_Device):
|
||||
class Device(Device):
|
||||
'''
|
||||
This class provides logic common to all drivers for devices that export themselves
|
||||
as USB Mass Storage devices. If you are writing such a driver, inherit from this
|
||||
@ -83,7 +83,7 @@ class Device(_Device):
|
||||
FDI_BCD_TEMPLATE = '<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.device_revision_bcd" int="%(bcd)s">'
|
||||
|
||||
|
||||
def __init__(self, key='-1', log_packets=False, report_progress=None) :
|
||||
def reset(self, key='-1', log_packets=False, report_progress=None) :
|
||||
self._main_prefix = self._card_a_prefix = self._card_b_prefix = None
|
||||
|
||||
@classmethod
|
||||
|
@ -10,7 +10,6 @@ for a particular device.
|
||||
import os, fnmatch, shutil
|
||||
from itertools import cycle
|
||||
|
||||
from calibre.ebooks.metadata.meta import metadata_from_formats, path_to_ext
|
||||
from calibre.ebooks.metadata import authors_to_string
|
||||
from calibre.devices.usbms.cli import CLI
|
||||
from calibre.devices.usbms.device import Device
|
||||
@ -21,6 +20,12 @@ from calibre.devices.mime import mime_type_ext
|
||||
# CLI must come before Device as it implments the CLI functions that
|
||||
# are inherited from the device interface in Device.
|
||||
class USBMS(CLI, Device):
|
||||
|
||||
name = 'USBMS Base Device Interface'
|
||||
description = _('Communicate with an eBook reader.')
|
||||
author = _('John Schember')
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
|
||||
FORMATS = []
|
||||
EBOOK_DIR_MAIN = ''
|
||||
EBOOK_DIR_CARD_A = ''
|
||||
@ -28,8 +33,8 @@ class USBMS(CLI, Device):
|
||||
SUPPORTS_SUB_DIRS = False
|
||||
CAN_SET_METADATA = False
|
||||
|
||||
def __init__(self, key='-1', log_packets=False, report_progress=None):
|
||||
Device.__init__(self, key=key, log_packets=log_packets,
|
||||
def reset(self, key='-1', log_packets=False, report_progress=None):
|
||||
Device.reset(self, key=key, log_packets=log_packets,
|
||||
report_progress=report_progress)
|
||||
|
||||
def get_device_information(self, end_session=True):
|
||||
@ -40,6 +45,7 @@ class USBMS(CLI, Device):
|
||||
return (self.__class__.__name__, '', '', '')
|
||||
|
||||
def books(self, oncard=None, end_session=True):
|
||||
from calibre.ebooks.metadata.meta import path_to_ext
|
||||
bl = BookList()
|
||||
|
||||
if oncard == 'carda' and not self._card_a_prefix:
|
||||
@ -190,10 +196,12 @@ class USBMS(CLI, Device):
|
||||
|
||||
@classmethod
|
||||
def metadata_from_path(cls, path):
|
||||
from calibre.ebooks.metadata.meta import metadata_from_formats
|
||||
return metadata_from_formats([path])
|
||||
|
||||
@classmethod
|
||||
def book_from_path(cls, path):
|
||||
from calibre.ebooks.metadata.meta import path_to_ext
|
||||
fileext = path_to_ext(path)
|
||||
mi = cls.metadata_from_path(path)
|
||||
mime = mime_type_ext(fileext)
|
||||
|
@ -95,6 +95,18 @@ class HTMLPreProcessor(object):
|
||||
|
||||
# Fix pdftohtml markup
|
||||
PDFTOHTML = [
|
||||
# Fix umlauts
|
||||
(re.compile(u'¨\s*(<br.*?>)*\s*o', re.UNICODE), lambda match: u'ö'),
|
||||
(re.compile(u'¨\s*(<br.*?>)*\s*O', re.UNICODE), lambda match: u'Ö'),
|
||||
(re.compile(u'¨\s*(<br.*?>)*\s*u', re.UNICODE), lambda match: u'ü'),
|
||||
(re.compile(u'¨\s*(<br.*?>)*\s*U', re.UNICODE), lambda match: u'Ü'),
|
||||
(re.compile(u'¨\s*(<br.*?>)*\s*e', re.UNICODE), lambda match: u'ë'),
|
||||
(re.compile(u'¨\s*(<br.*?>)*\s*E', re.UNICODE), lambda match: u'Ë'),
|
||||
(re.compile(u'¨\s*(<br.*?>)*\s*i', re.UNICODE), lambda match: u'ï'),
|
||||
(re.compile(u'¨\s*(<br.*?>)*\s*I', re.UNICODE), lambda match: u'Ï'),
|
||||
(re.compile(u'¨\s*(<br.*?>)*\s*a', re.UNICODE), lambda match: u'ä'),
|
||||
(re.compile(u'¨\s*(<br.*?>)*\s*A', re.UNICODE), lambda match: u'Ä'),
|
||||
|
||||
# Remove page links
|
||||
(re.compile(r'<a name=\d+></a>', re.IGNORECASE), lambda match: ''),
|
||||
# Remove <hr> tags
|
||||
|
90
src/calibre/ebooks/pdb/ereader/inspector.py
Normal file
90
src/calibre/ebooks/pdb/ereader/inspector.py
Normal file
@ -0,0 +1,90 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Inspect the header of ereader files. This is primarily used for debugging.
|
||||
'''
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import struct, sys
|
||||
|
||||
from calibre.ebooks.pdb.header import PdbHeaderReader
|
||||
from calibre.ebooks.pdb.ereader.reader import HeaderRecord
|
||||
|
||||
def pdb_header_info(header):
|
||||
print 'PDB Header Info:'
|
||||
print ''
|
||||
print 'Identity: %s' % header.ident
|
||||
print 'Total Sectons: %s' % header.num_sections
|
||||
print 'Title: %s' % header.title
|
||||
print ''
|
||||
|
||||
def ereader_header_info(header):
|
||||
h0 = header.section_data(0)
|
||||
|
||||
print 'Ereader Record 0 (Header) Info:'
|
||||
print ''
|
||||
print '0-2 Version: %i' % struct.unpack('>H', h0[0:2])[0]
|
||||
print '2-4: %i' % struct.unpack('>H', h0[2:4])[0]
|
||||
print '4-6: %i' % struct.unpack('>H', h0[4:6])[0]
|
||||
print '6-8: %i' % struct.unpack('>H', h0[6:8])[0]
|
||||
print '8-10: %i' % struct.unpack('>H', h0[8:10])[0]
|
||||
print '10-12: %i' % struct.unpack('>H', h0[10:12])[0]
|
||||
print '12-14 Non-Text: %i' % struct.unpack('>H', h0[12:14])[0]
|
||||
print '14-16: %i' % struct.unpack('>H', h0[14:16])[0]
|
||||
print '16-18: %i' % struct.unpack('>H', h0[16:18])[0]
|
||||
print '18-20: %i' % struct.unpack('>H', h0[18:20])[0]
|
||||
print '20-22: %i' % struct.unpack('>H', h0[20:22])[0]
|
||||
print '22-24: %i' % struct.unpack('>H', h0[22:24])[0]
|
||||
print '24-26: %i' % struct.unpack('>H', h0[24:26])[0]
|
||||
print '26-28: %i' % struct.unpack('>H', h0[26:28])[0]
|
||||
print '28-30 footnote_rec: %i' % struct.unpack('>H', h0[28:30])[0]
|
||||
print '30-32 sidebar_rec: %i' % struct.unpack('>H', h0[30:32])[0]
|
||||
print '32-34 bookmark_offset: %i' % struct.unpack('>H', h0[32:34])[0]
|
||||
print '34-36: %i' % struct.unpack('>H', h0[34:36])[0]
|
||||
print '36-38: %i' % struct.unpack('>H', h0[36:38])[0]
|
||||
print '38-40: %i' % struct.unpack('>H', h0[38:40])[0]
|
||||
print '40-42 image_data_offset: %i' % struct.unpack('>H', h0[40:42])[0]
|
||||
print '42-44: %i' % struct.unpack('>H', h0[42:44])[0]
|
||||
print '44-46 metadata_offset: %i' % struct.unpack('>H', h0[44:46])[0]
|
||||
print '46-48: %i' % struct.unpack('>H', h0[46:48])[0]
|
||||
print '48-50 footnote_offset: %i' % struct.unpack('>H', h0[48:50])[0]
|
||||
print '50-52 sidebar_offset: %i' % struct.unpack('>H', h0[50:52])[0]
|
||||
print '52-54 last_data_offset: %i' % struct.unpack('>H', h0[52:54])[0]
|
||||
|
||||
for i in range(54, 131, 2):
|
||||
print '%i-%i: %i' % (i, i+2, struct.unpack('>H', h0[i:i+2])[0])
|
||||
|
||||
print ''
|
||||
|
||||
def section_lengths(header):
|
||||
print 'Section Sizes'
|
||||
print ''
|
||||
|
||||
for i in range(0, header.section_count()):
|
||||
size = len(header.section_data(i))
|
||||
if size > 65505:
|
||||
message = '<--- Over!'
|
||||
else:
|
||||
message = ''
|
||||
|
||||
print 'Section %i: %i %s' % (i, size, message)
|
||||
|
||||
def main(args=sys.argv):
|
||||
if len(args) < 2:
|
||||
print 'Error: requires input file.'
|
||||
return 1
|
||||
|
||||
f = open(sys.argv[1], 'rb')
|
||||
|
||||
pheader = PdbHeaderReader(f)
|
||||
|
||||
pdb_header_info(pheader)
|
||||
ereader_header_info(pheader)
|
||||
section_lengths(pheader)
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
@ -27,11 +27,11 @@ class Writer(object):
|
||||
|
||||
hr = [self._header_record(len(text), len(images))]
|
||||
|
||||
sections = hr+text+images+metadata
|
||||
sections = hr+text+images+metadata+['MeTaInFo\x00']
|
||||
|
||||
lengths = [len(i) for i in sections]
|
||||
|
||||
pdbHeaderBuilder = PdbHeaderBuilder(IDENTITY, '')
|
||||
pdbHeaderBuilder = PdbHeaderBuilder(IDENTITY, 'test book')
|
||||
pdbHeaderBuilder.build_header(lengths, out_stream)
|
||||
|
||||
for item in sections:
|
||||
@ -69,7 +69,7 @@ class Writer(object):
|
||||
return images
|
||||
|
||||
def _metadata(self, metadata):
|
||||
return '\x00\x00\x00\x00\x00'
|
||||
return 'test\x00\x00\x00\x00\x00'
|
||||
|
||||
def _header_record(self, text_items, image_items):
|
||||
'''
|
||||
@ -82,14 +82,47 @@ class Writer(object):
|
||||
if image_items > 0:
|
||||
image_data_offset = text_items + 1
|
||||
meta_data_offset = image_data_offset + image_items
|
||||
last_data_offset = meta_data_offset + 1
|
||||
last_data_offset = meta_data_offset + 2
|
||||
else:
|
||||
meta_data_offset = text_items + 1
|
||||
last_data_offset = meta_data_offset + 1
|
||||
image_data_offset = last_data_offset
|
||||
|
||||
record = u''
|
||||
record = ''
|
||||
|
||||
record += struct.pack('>H', version) # [0:2]
|
||||
record += struct.pack('>H', 0) # [2:4]
|
||||
record += struct.pack('>H', 0) # [4:6]
|
||||
record += struct.pack('>H', 25152) # [6:8] # 25152 is MAGIC
|
||||
record += struct.pack('>H', last_data_offset) # [8:10]
|
||||
record += struct.pack('>H', last_data_offset) # [10:12]
|
||||
record += struct.pack('>H', non_text_offset) # [12:14] # non_text_offset
|
||||
record += struct.pack('>H', non_text_offset) # [14:16]
|
||||
record += struct.pack('>H', 1) # [16:18]
|
||||
record += struct.pack('>H', 1) # [18:20]
|
||||
record += struct.pack('>H', 0) # [20:22]
|
||||
record += struct.pack('>H', 1) # [22:24]
|
||||
record += struct.pack('>H', 1) # [24:26]
|
||||
record += struct.pack('>H', 0) # [26:28]
|
||||
record += struct.pack('>H', 0) # [28:30] # footnote_rec
|
||||
record += struct.pack('>H', 0) # [30:32] # sidebar_rec
|
||||
record += struct.pack('>H', last_data_offset) # [32:34] # bookmark_offset
|
||||
record += struct.pack('>H', 2560) # [34:36] # 2560 is MAGIC
|
||||
record += struct.pack('>H', non_text_offset) # [36:38]
|
||||
record += struct.pack('>H', non_text_offset + 1) # [38:40]
|
||||
record += struct.pack('>H', image_data_offset) # [40:42]
|
||||
record += struct.pack('>H', image_data_offset) # [42:44]
|
||||
record += struct.pack('>H', meta_data_offset) # [44:46]
|
||||
record += struct.pack('>H', meta_data_offset) # [46:48]
|
||||
record += struct.pack('>H', last_data_offset) # [48:50] # footnote_offset
|
||||
record += struct.pack('>H', last_data_offset) # [50:52] # sidebar_offset
|
||||
record += struct.pack('>H', last_data_offset) # [52:54] # last_data_offset
|
||||
|
||||
record += struct.pack('>H', 1) # [54:56]
|
||||
for i in range(56, 132, 2):
|
||||
record += struct.pack('>H', 0)
|
||||
|
||||
'''
|
||||
# Version
|
||||
record += struct.pack('>H', version)
|
||||
record = record.ljust(12, '\x00')
|
||||
@ -112,6 +145,6 @@ class Writer(object):
|
||||
record += struct.pack('>H', last_data_offset)
|
||||
record = record.ljust(52, '\x00')
|
||||
record += struct.pack('>H', last_data_offset)
|
||||
|
||||
'''
|
||||
return record
|
||||
|
||||
|
@ -16,7 +16,7 @@ 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, decrypt, encrypt, \
|
||||
info, merge, reverse, split
|
||||
info, merge, reverse, rotate, split
|
||||
|
||||
COMMANDS = {
|
||||
'crop' : crop,
|
||||
@ -25,6 +25,7 @@ COMMANDS = {
|
||||
'info' : info,
|
||||
'merge' : merge,
|
||||
'reverse' : reverse,
|
||||
'rotate' : rotate,
|
||||
'split' : split,
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ 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
|
||||
from calibre.ebooks.pdf.verify import is_valid_pdf, is_encrypted
|
||||
|
||||
from pyPdf import PdfFileWriter, PdfFileReader
|
||||
|
||||
|
@ -16,7 +16,7 @@ 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, is_encrypted
|
||||
from calibre.ebooks.pdf.verify import is_valid_pdfs, is_encrypted, is_encrypted
|
||||
|
||||
from pyPdf import PdfFileWriter, PdfFileReader
|
||||
|
||||
@ -42,10 +42,10 @@ def print_info(pdf_path):
|
||||
print _('Subject: %s' % pdf.documentInfo.subject)
|
||||
print _('Creator: %s' % pdf.documentInfo.creator)
|
||||
print _('Producer: %s' % pdf.documentInfo.producer)
|
||||
print _('Creation Date: %s' % time.strftime('%a %b %d %H:%M:%S %Y', time.gmtime(os.path.getctime(pdf_path))))
|
||||
print _('Modification Date: %s' % time.strftime('%a %b %d %H:%M:%S %Y', time.gmtime(os.path.getmtime(pdf_path))))
|
||||
#print _('Creation Date: %s' % time.strftime('%a %b %d %H:%M:%S %Y', time.gmtime(os.path.getctime(pdf_path))))
|
||||
#print _('Modification Date: %s' % time.strftime('%a %b %d %H:%M:%S %Y', time.gmtime(os.path.getmtime(pdf_path))))
|
||||
print _('Pages: %s' % pdf.numPages)
|
||||
print _('Encrypted: %s' % pdf.isEncrypted)
|
||||
#print _('Encrypted: %s' % pdf.isEncrypted)
|
||||
try:
|
||||
print _('File Size: %s bytes' % os.path.getsize(pdf_path))
|
||||
except: pass
|
||||
|
@ -18,7 +18,7 @@ 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
|
||||
|
||||
|
@ -18,7 +18,7 @@ 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
|
||||
from calibre.ebooks.pdf.verify import is_valid_pdf, is_encrypted
|
||||
|
||||
from pyPdf import PdfFileWriter, PdfFileReader
|
||||
|
||||
|
105
src/calibre/ebooks/pdf/manipulate/rotate.py
Normal file
105
src/calibre/ebooks/pdf/manipulate/rotate.py
Normal file
@ -0,0 +1,105 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
'''
|
||||
Rotate pages of a 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 ' + _('''\
|
||||
file.pdf degrees
|
||||
|
||||
Rotate pages of a PDF clockwise.
|
||||
''')
|
||||
|
||||
OPTIONS = set([
|
||||
OptionRecommendation(name='output', recommended_value='rotated.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, _('Rotate 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 rotate(pdf_path, out_path, degrees, 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.rotateClockwise(int(degrees)))
|
||||
|
||||
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 how many degrees to rotate 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 encrypted.' % args[0]
|
||||
return 1
|
||||
|
||||
mi = metadata_from_formats([args[0]])
|
||||
|
||||
rotate(args[0], opts.output, args[1], mi)
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
@ -18,7 +18,7 @@ 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
|
||||
from calibre.ebooks.pdf.verify import is_valid_pdf, is_encrypted
|
||||
|
||||
from pyPdf import PdfFileWriter, PdfFileReader
|
||||
|
||||
|
@ -16,8 +16,9 @@ import os, glob
|
||||
from calibre.customize.conversion import OutputFormatPlugin, \
|
||||
OptionRecommendation
|
||||
from calibre.ebooks.oeb.output import OEBOutput
|
||||
from calibre.ebooks.metadata.opf2 import OPF
|
||||
from calibre.ptempfile import TemporaryDirectory
|
||||
from calibre.ebooks.pdf.writer import PDFWriter, PDFMetadata
|
||||
from calibre.ebooks.pdf.writer import PDFWriter, ImagePDFWriter, PDFMetadata
|
||||
from calibre.ebooks.pdf.pageoptions import UNITS, PAPER_SIZES, \
|
||||
ORIENTATIONS
|
||||
|
||||
@ -28,23 +29,11 @@ class PDFOutput(OutputFormatPlugin):
|
||||
file_type = 'pdf'
|
||||
|
||||
options = set([
|
||||
OptionRecommendation(name='margin_top', recommended_value='1',
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The top margin around the document.')),
|
||||
OptionRecommendation(name='margin_bottom', recommended_value='1',
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The bottom margin around the document.')),
|
||||
OptionRecommendation(name='margin_left', recommended_value='1',
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The left margin around the document.')),
|
||||
OptionRecommendation(name='margin_right', recommended_value='1',
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The right margin around the document.')),
|
||||
|
||||
OptionRecommendation(name='unit', recommended_value='inch',
|
||||
level=OptionRecommendation.LOW, short_switch='u', choices=UNITS.keys(),
|
||||
help=_('The unit of measure. Default is inch. Choices '
|
||||
'are %s' % UNITS.keys())),
|
||||
'are %s '
|
||||
'Note: This does not override the unit for margins!' % UNITS.keys())),
|
||||
OptionRecommendation(name='paper_size', recommended_value='letter',
|
||||
level=OptionRecommendation.LOW, choices=PAPER_SIZES.keys(),
|
||||
help=_('The size of the paper. Default is letter. Choices '
|
||||
@ -60,28 +49,43 @@ class PDFOutput(OutputFormatPlugin):
|
||||
])
|
||||
|
||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||
self.opts, self.log = opts, log
|
||||
self.input_plugin, self.opts, self.log = input_plugin, opts, log
|
||||
self.output_path = output_path
|
||||
self.metadata = oeb_book.metadata
|
||||
|
||||
if input_plugin.is_image_collection:
|
||||
self.convert_images(input_plugin.get_images())
|
||||
else:
|
||||
self.convert_text(oeb_book)
|
||||
|
||||
def convert_images(self, images):
|
||||
self.write(ImagePDFWriter, images)
|
||||
|
||||
def convert_text(self, oeb_book):
|
||||
with TemporaryDirectory('_pdf_out') as oebdir:
|
||||
OEBOutput(None).convert(oeb_book, oebdir, input_plugin, opts, log)
|
||||
OEBOutput(None).convert(oeb_book, oebdir, self.input_plugin, self.opts, self.log)
|
||||
|
||||
opf = glob.glob(os.path.join(oebdir, '*.opf'))[0]
|
||||
opfpath = glob.glob(os.path.join(oebdir, '*.opf'))[0]
|
||||
opf = OPF(opfpath, os.path.dirname(opfpath))
|
||||
|
||||
self.write(PDFWriter, [s.path for s in opf.spine])
|
||||
|
||||
writer = PDFWriter(log, opts)
|
||||
def write(self, Writer, items):
|
||||
writer = Writer(self.opts, self.log)
|
||||
|
||||
close = False
|
||||
if not hasattr(output_path, 'write'):
|
||||
close = True
|
||||
if not os.path.exists(os.path.dirname(output_path)) and os.path.dirname(output_path) != '':
|
||||
os.makedirs(os.path.dirname(output_path))
|
||||
out_stream = open(output_path, 'wb')
|
||||
else:
|
||||
out_stream = output_path
|
||||
close = False
|
||||
if not hasattr(self.output_path, 'write'):
|
||||
close = True
|
||||
if not os.path.exists(os.path.dirname(self.output_path)) and os.path.dirname(self.output_path) != '':
|
||||
os.makedirs(os.path.dirname(self.output_path))
|
||||
out_stream = open(self.output_path, 'wb')
|
||||
else:
|
||||
out_stream = self.output_path
|
||||
|
||||
out_stream.seek(0)
|
||||
out_stream.truncate()
|
||||
writer.dump(opf, out_stream, PDFMetadata(oeb_book.metadata))
|
||||
out_stream.seek(0)
|
||||
out_stream.truncate()
|
||||
writer.dump(items, out_stream, PDFMetadata(self.metadata))
|
||||
|
||||
if close:
|
||||
out_stream.close()
|
||||
|
||||
if close:
|
||||
out_stream.close()
|
||||
|
@ -15,7 +15,6 @@ from calibre.ptempfile import PersistentTemporaryDirectory
|
||||
from calibre.ebooks.pdf.pageoptions import unit, paper_size, \
|
||||
orientation, size
|
||||
from calibre.ebooks.metadata import authors_to_string
|
||||
from calibre.ebooks.metadata.opf2 import OPF
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from PyQt4.Qt import QUrl, QEventLoop, SIGNAL, QObject, \
|
||||
@ -37,7 +36,7 @@ class PDFMetadata(object):
|
||||
|
||||
|
||||
class PDFWriter(QObject):
|
||||
def __init__(self, log, opts):
|
||||
def __init__(self, opts, log):
|
||||
if QApplication.instance() is None:
|
||||
QApplication([])
|
||||
QObject.__init__(self)
|
||||
@ -63,19 +62,42 @@ class PDFWriter(QObject):
|
||||
self.custom_size = None
|
||||
|
||||
self.opts = opts
|
||||
|
||||
self.size = self._size()
|
||||
|
||||
def dump(self, opfpath, out_stream, pdf_metadata):
|
||||
def dump(self, items, out_stream, pdf_metadata):
|
||||
self.metadata = pdf_metadata
|
||||
self._delete_tmpdir()
|
||||
|
||||
opf = OPF(opfpath, os.path.dirname(opfpath))
|
||||
self.render_queue = [i.path for i in opf.spine]
|
||||
self.render_queue = items
|
||||
self.combine_queue = []
|
||||
self.out_stream = out_stream
|
||||
|
||||
QMetaObject.invokeMethod(self, "_render_book", Qt.QueuedConnection)
|
||||
self.loop.exec_()
|
||||
|
||||
def _size(self):
|
||||
'''
|
||||
The size of a pdf page in cm.
|
||||
'''
|
||||
printer = QPrinter(QPrinter.HighResolution)
|
||||
|
||||
if self.opts.output_profile.short_name == 'default':
|
||||
if self.custom_size == None:
|
||||
printer.setPaperSize(paper_size(self.opts.paper_size))
|
||||
else:
|
||||
printer.setPaperSize(QSizeF(self.custom_size[0], self.custom_size[1]), unit(self.opts.unit))
|
||||
else:
|
||||
printer.setPaperSize(QSizeF(self.opts.output_profile.width / self.opts.output_profile.dpi, self.opts.output_profile.height / self.opts.output_profile.dpi), QPrinter.Inch)
|
||||
|
||||
printer.setPageMargins(0, 0, 0, 0, QPrinter.Point)
|
||||
printer.setOrientation(orientation(self.opts.orientation))
|
||||
printer.setOutputFormat(QPrinter.PdfFormat)
|
||||
|
||||
size = printer.paperSize(QPrinter.Millimeter)
|
||||
|
||||
return size.width() / 10, size.height() / 10
|
||||
|
||||
@QtCore.pyqtSignature('_render_book()')
|
||||
def _render_book(self):
|
||||
if len(self.render_queue) == 0:
|
||||
@ -87,7 +109,7 @@ class PDFWriter(QObject):
|
||||
item = str(self.render_queue.pop(0))
|
||||
self.combine_queue.append(os.path.join(self.tmp_path, '%i.pdf' % (len(self.combine_queue) + 1)))
|
||||
|
||||
self.logger.info('Processing %s...' % item)
|
||||
self.logger.debug('Processing %s...' % item)
|
||||
|
||||
self.view.load(QUrl(item))
|
||||
|
||||
@ -98,16 +120,8 @@ class PDFWriter(QObject):
|
||||
self.logger.debug('\tRendering item %s as %i' % (os.path.basename(str(self.view.url().toLocalFile())), len(self.combine_queue)))
|
||||
|
||||
printer = QPrinter(QPrinter.HighResolution)
|
||||
|
||||
if self.opts.output_profile.short_name == 'default':
|
||||
if self.custom_size == None:
|
||||
printer.setPaperSize(paper_size(self.opts.paper_size))
|
||||
else:
|
||||
printer.setPaperSize(QSizeF(self.custom_size[0], self.custom_size[1]), unit(self.opts.unit))
|
||||
else:
|
||||
printer.setPaperSize(QSizeF(self.opts.output_profile.width / self.opts.output_profile.dpi, self.opts.output_profile.height / self.opts.output_profile.dpi), QPrinter.Inch)
|
||||
|
||||
printer.setPageMargins(size(self.opts.margin_left), size(self.opts.margin_top), size(self.opts.margin_right), size(self.opts.margin_bottom), unit(self.opts.unit))
|
||||
printer.setPaperSize(QSizeF(self.size[0] * 10, self.size[1] * 10), QPrinter.Millimeter)
|
||||
printer.setPageMargins(0, 0, 0, 0, QPrinter.Point)
|
||||
printer.setOrientation(orientation(self.opts.orientation))
|
||||
printer.setOutputFormat(QPrinter.PdfFormat)
|
||||
printer.setOutputFileName(item_path)
|
||||
@ -120,7 +134,7 @@ class PDFWriter(QObject):
|
||||
self.tmp_path = PersistentTemporaryDirectory('_pdf_output_parts')
|
||||
|
||||
def _write(self):
|
||||
self.logger.info('Combining individual PDF parts...')
|
||||
self.logger.debug('Combining individual PDF parts...')
|
||||
|
||||
try:
|
||||
outPDF = PdfFileWriter(title=self.metadata.title, author=self.metadata.author)
|
||||
@ -132,3 +146,38 @@ class PDFWriter(QObject):
|
||||
finally:
|
||||
self._delete_tmpdir()
|
||||
self.loop.exit(0)
|
||||
|
||||
|
||||
class ImagePDFWriter(PDFWriter):
|
||||
|
||||
def _render_next(self):
|
||||
item = str(self.render_queue.pop(0))
|
||||
self.combine_queue.append(os.path.join(self.tmp_path, '%i.pdf' % (len(self.combine_queue) + 1)))
|
||||
|
||||
self.logger.debug('Processing %s...' % item)
|
||||
|
||||
height = 'height: %fcm;' % (self.size[1] * 1.3)
|
||||
|
||||
html = '<html><body style="margin: 0;"><img src="%s" style="%s display: block; margin-left: auto; margin-right: auto; padding: 0px;" /></body></html>' % (item, height)
|
||||
|
||||
self.view.setHtml(html)
|
||||
|
||||
def _size(self):
|
||||
printer = QPrinter(QPrinter.HighResolution)
|
||||
|
||||
if self.opts.output_profile.short_name == 'default':
|
||||
if self.custom_size == None:
|
||||
printer.setPaperSize(paper_size(self.opts.paper_size))
|
||||
else:
|
||||
printer.setPaperSize(QSizeF(self.custom_size[0], self.custom_size[1]), unit(self.opts.unit))
|
||||
else:
|
||||
printer.setPaperSize(QSizeF(self.opts.output_profile.comic_screen_size[0] / self.opts.output_profile.dpi, self.opts.output_profile.comic_screen_size[1] / self.opts.output_profile.dpi), QPrinter.Inch)
|
||||
|
||||
printer.setPageMargins(0, 0, 0, 0, QPrinter.Point)
|
||||
printer.setOrientation(orientation(self.opts.orientation))
|
||||
printer.setOutputFormat(QPrinter.PdfFormat)
|
||||
|
||||
size = printer.paperSize(QPrinter.Millimeter)
|
||||
|
||||
return size.width() / 10, size.height() / 10
|
||||
|
||||
|
@ -10,8 +10,8 @@ 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.customize.ui import available_input_formats, available_output_formats, \
|
||||
device_plugins
|
||||
from calibre.constants import iswindows
|
||||
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
||||
from calibre.parallel import Job
|
||||
@ -21,7 +21,6 @@ from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \
|
||||
info_dialog
|
||||
from calibre.ebooks.metadata import authors_to_string
|
||||
from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog
|
||||
from calibre.devices.interface import Device
|
||||
from calibre import sanitize_file_name, preferred_encoding
|
||||
from calibre.utils.filenames import ascii_filename
|
||||
from calibre.devices.errors import FreeSpaceError
|
||||
@ -54,7 +53,7 @@ class DeviceManager(Thread):
|
||||
'''
|
||||
Thread.__init__(self)
|
||||
self.setDaemon(True)
|
||||
self.devices = [[d, False] for d in devices()]
|
||||
self.devices = [[d, False] for d in device_plugins()]
|
||||
self.device = None
|
||||
self.device_class = None
|
||||
self.sleep_time = sleep_time
|
||||
@ -71,7 +70,8 @@ class DeviceManager(Thread):
|
||||
connected = self.scanner.is_device_connected(device[0])
|
||||
if connected and not device[1]:
|
||||
try:
|
||||
dev = device[0]()
|
||||
dev = device[0]
|
||||
dev.reset()
|
||||
if iswindows:
|
||||
import pythoncom
|
||||
pythoncom.CoInitialize()
|
||||
|
Loading…
x
Reference in New Issue
Block a user