mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Kindle driver: Add an option to allow using page counts stored in a custom column. Go to Preferences->Plugins and customize the Kindle driver, to tell it to use a custom column to get page count data.
This commit is contained in:
parent
0b4f34cb2d
commit
bd27557d58
@ -19,7 +19,12 @@ class APNXBuilder(object):
|
|||||||
Create an APNX file using a pseudo page mapping.
|
Create an APNX file using a pseudo page mapping.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def write_apnx(self, mobi_file_path, apnx_path, accurate=True):
|
def write_apnx(self, mobi_file_path, apnx_path, accurate=True, page_count=0):
|
||||||
|
'''
|
||||||
|
If you want a fixed number of pages (such as from a custom column) then
|
||||||
|
pass in a value to page_count, otherwise a count will be estimated
|
||||||
|
using either the fast or accurate algorithm.
|
||||||
|
'''
|
||||||
# Check that this is really a MOBI file.
|
# Check that this is really a MOBI file.
|
||||||
with open(mobi_file_path, 'rb') as mf:
|
with open(mobi_file_path, 'rb') as mf:
|
||||||
ident = PdbHeaderReader(mf).identity()
|
ident = PdbHeaderReader(mf).identity()
|
||||||
@ -28,16 +33,19 @@ class APNXBuilder(object):
|
|||||||
|
|
||||||
# Get the pages depending on the chosen parser
|
# Get the pages depending on the chosen parser
|
||||||
pages = []
|
pages = []
|
||||||
if accurate:
|
if page_count:
|
||||||
try:
|
pages = self.get_pages_exact(mobi_file_path, page_count)
|
||||||
pages = self.get_pages_accurate(mobi_file_path)
|
|
||||||
except:
|
|
||||||
# Fall back to the fast parser if we can't
|
|
||||||
# use the accurate one. Typically this is
|
|
||||||
# due to the file having DRM.
|
|
||||||
pages = self.get_pages_fast(mobi_file_path)
|
|
||||||
else:
|
else:
|
||||||
pages = self.get_pages_fast(mobi_file_path)
|
if accurate:
|
||||||
|
try:
|
||||||
|
pages = self.get_pages_accurate(mobi_file_path)
|
||||||
|
except:
|
||||||
|
# Fall back to the fast parser if we can't
|
||||||
|
# use the accurate one. Typically this is
|
||||||
|
# due to the file having DRM.
|
||||||
|
pages = self.get_pages_fast(mobi_file_path)
|
||||||
|
else:
|
||||||
|
pages = self.get_pages_fast(mobi_file_path)
|
||||||
|
|
||||||
if not pages:
|
if not pages:
|
||||||
raise Exception(_('Could not generate page mapping.'))
|
raise Exception(_('Could not generate page mapping.'))
|
||||||
@ -77,6 +85,31 @@ class APNXBuilder(object):
|
|||||||
|
|
||||||
return apnx
|
return apnx
|
||||||
|
|
||||||
|
def get_pages_exact(self, mobi_file_path, page_count):
|
||||||
|
'''
|
||||||
|
Given a specified page count (such as from a custom column),
|
||||||
|
create our array of pages for the apnx file by dividing by
|
||||||
|
the content size of the book.
|
||||||
|
'''
|
||||||
|
pages = []
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
with open(mobi_file_path, 'rb') as mf:
|
||||||
|
phead = PdbHeaderReader(mf)
|
||||||
|
r0 = phead.section_data(0)
|
||||||
|
text_length = struct.unpack('>I', r0[4:8])[0]
|
||||||
|
|
||||||
|
chars_per_page = int(text_length / page_count)
|
||||||
|
while count < text_length:
|
||||||
|
pages.append(count)
|
||||||
|
count += chars_per_page
|
||||||
|
|
||||||
|
if len(pages) > page_count:
|
||||||
|
# Rounding created extra page entries
|
||||||
|
pages = pages[:page_count]
|
||||||
|
|
||||||
|
return pages
|
||||||
|
|
||||||
def get_pages_fast(self, mobi_file_path):
|
def get_pages_fast(self, mobi_file_path):
|
||||||
'''
|
'''
|
||||||
2300 characters of uncompressed text per page. This is
|
2300 characters of uncompressed text per page. This is
|
||||||
|
@ -302,19 +302,28 @@ class KINDLE2(KINDLE):
|
|||||||
' this information to the Kindle when uploading MOBI files by'
|
' this information to the Kindle when uploading MOBI files by'
|
||||||
' USB. Note that the page numbers do not correspond to any paper'
|
' USB. Note that the page numbers do not correspond to any paper'
|
||||||
' book.'),
|
' book.'),
|
||||||
_('Use slower but more accurate page number generation') +
|
_('Use slower but more accurate page number calculation') +
|
||||||
':::' +
|
':::' +
|
||||||
_('There are two ways to generate the page number information. Using the more accurate '
|
_('There are two ways to generate the page number information. Using the more accurate '
|
||||||
'generator will produce pages that correspond better to a printed book. '
|
'generator will produce pages that correspond better to a printed book. '
|
||||||
'However, this method is slower and will slow down sending files '
|
'However, this method is slower and will slow down sending files '
|
||||||
'to the Kindle.'),
|
'to the Kindle.'),
|
||||||
|
_('Custom column name to retrieve page counts from') +
|
||||||
|
':::' +
|
||||||
|
_('If you have a custom column in your library that you use to '
|
||||||
|
'store the page count of books, you can have calibre use that '
|
||||||
|
'information, instead of calculating a page count. Specify the '
|
||||||
|
'name of the custom column here, for example, #pages. '),
|
||||||
|
|
||||||
]
|
]
|
||||||
EXTRA_CUSTOMIZATION_DEFAULT = [
|
EXTRA_CUSTOMIZATION_DEFAULT = [
|
||||||
True,
|
True,
|
||||||
False,
|
False,
|
||||||
|
'',
|
||||||
]
|
]
|
||||||
OPT_APNX = 0
|
OPT_APNX = 0
|
||||||
OPT_APNX_ACCURATE = 1
|
OPT_APNX_ACCURATE = 1
|
||||||
|
OPT_APNX_CUST_COL = 2
|
||||||
|
|
||||||
def books(self, oncard=None, end_session=True):
|
def books(self, oncard=None, end_session=True):
|
||||||
bl = USBMS.books(self, oncard=oncard, end_session=end_session)
|
bl = USBMS.books(self, oncard=oncard, end_session=end_session)
|
||||||
@ -380,10 +389,20 @@ class KINDLE2(KINDLE):
|
|||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
|
|
||||||
|
cust_col_name = opts.extra_customization[self.OPT_APNX_CUST_COL]
|
||||||
|
custom_page_count = 0
|
||||||
|
if cust_col_name:
|
||||||
|
try:
|
||||||
|
custom_page_count = int(metadata.get(cust_col_name, 0))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
apnx_path = '%s.apnx' % os.path.join(path, filename)
|
apnx_path = '%s.apnx' % os.path.join(path, filename)
|
||||||
apnx_builder = APNXBuilder()
|
apnx_builder = APNXBuilder()
|
||||||
try:
|
try:
|
||||||
apnx_builder.write_apnx(filepath, apnx_path, accurate=opts.extra_customization[self.OPT_APNX_ACCURATE])
|
apnx_builder.write_apnx(filepath, apnx_path,
|
||||||
|
accurate=opts.extra_customization[self.OPT_APNX_ACCURATE],
|
||||||
|
page_count=custom_page_count)
|
||||||
except:
|
except:
|
||||||
print 'Failed to generate APNX'
|
print 'Failed to generate APNX'
|
||||||
import traceback
|
import traceback
|
||||||
|
@ -82,6 +82,7 @@ class ConfigWidget(QWidget, Ui_ConfigWidget):
|
|||||||
self.opt_extra_customization.append(QLineEdit(self))
|
self.opt_extra_customization.append(QLineEdit(self))
|
||||||
l = QLabel(label_text)
|
l = QLabel(label_text)
|
||||||
l.setToolTip(tt)
|
l.setToolTip(tt)
|
||||||
|
self.opt_extra_customization[i].setToolTip(tt)
|
||||||
l.setBuddy(self.opt_extra_customization[i])
|
l.setBuddy(self.opt_extra_customization[i])
|
||||||
l.setWordWrap(True)
|
l.setWordWrap(True)
|
||||||
self.opt_extra_customization[i].setText(settings.extra_customization[i])
|
self.opt_extra_customization[i].setText(settings.extra_customization[i])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user