Fix #2130 (Calibre Stops Reading MOBI Files)

This commit is contained in:
Kovid Goyal 2009-03-22 09:44:48 -07:00
parent aacd082e54
commit 802385787a

View File

@ -12,7 +12,7 @@ from PyQt4.Qt import QFontDatabase
from calibre.ebooks.epub.from_any import MAP from calibre.ebooks.epub.from_any import MAP
from calibre.ebooks.epub.from_html import TITLEPAGE from calibre.ebooks.epub.from_html import TITLEPAGE
from calibre.ebooks.epub import config from calibre.ebooks.epub import config
from calibre.ebooks.metadata.opf2 import OPF from calibre.ebooks.metadata.opf2 import OPF
from calibre.ptempfile import TemporaryDirectory from calibre.ptempfile import TemporaryDirectory
from calibre.ebooks.chardet import xml_to_unicode from calibre.ebooks.chardet import xml_to_unicode
@ -31,15 +31,15 @@ def character_count(html):
return count return count
class UnsupportedFormatError(Exception): class UnsupportedFormatError(Exception):
def __init__(self, fmt): def __init__(self, fmt):
Exception.__init__(self, _('%s format books are not supported')%fmt.upper()) Exception.__init__(self, _('%s format books are not supported')%fmt.upper())
class SpineItem(unicode): class SpineItem(unicode):
def __new__(cls, *args): def __new__(cls, *args):
obj = super(SpineItem, cls).__new__(cls, *args) obj = super(SpineItem, cls).__new__(cls, *args)
path = args[0] path = args[0].partition('#')[0]
raw = open(path, 'rb').read() raw = open(path, 'rb').read()
raw, obj.encoding = xml_to_unicode(raw) raw, obj.encoding = xml_to_unicode(raw)
obj.character_count = character_count(raw) obj.character_count = character_count(raw)
@ -63,9 +63,9 @@ def is_supported(path):
return ext in list(MAP.keys())+['html', 'opf'] return ext in list(MAP.keys())+['html', 'opf']
class EbookIterator(object): class EbookIterator(object):
CHARACTERS_PER_PAGE = 1000 CHARACTERS_PER_PAGE = 1000
def __init__(self, pathtoebook): def __init__(self, pathtoebook):
self.pathtoebook = os.path.abspath(pathtoebook) self.pathtoebook = os.path.abspath(pathtoebook)
self.config = DynamicConfig(name='iterator') self.config = DynamicConfig(name='iterator')
@ -77,17 +77,17 @@ class EbookIterator(object):
if ext not in map.keys(): if ext not in map.keys():
raise UnsupportedFormatError(ext) raise UnsupportedFormatError(ext)
self.to_opf = map[ext] self.to_opf = map[ext]
def search(self, text, index): def search(self, text, index):
text = text.lower() text = text.lower()
for i, path in enumerate(self.spine): for i, path in enumerate(self.spine):
if i > index: if i > index:
if text in open(path, 'rb').read().decode(path.encoding).lower(): if text in open(path, 'rb').read().decode(path.encoding).lower():
return i return i
def find_embedded_fonts(self): def find_embedded_fonts(self):
''' '''
This will become unnecessary once Qt WebKit supports the @font-face rule. This will become unnecessary once Qt WebKit supports the @font-face rule.
''' '''
for item in self.opf.manifest: for item in self.opf.manifest:
if item.mime_type and 'css' in item.mime_type.lower(): if item.mime_type and 'css' in item.mime_type.lower():
@ -108,7 +108,7 @@ class EbookIterator(object):
print 'WARNING: Family aliasing not supported:', block print 'WARNING: Family aliasing not supported:', block
else: else:
print 'Loaded embedded font:', repr(family) print 'Loaded embedded font:', repr(family)
def __enter__(self): def __enter__(self):
self._tdir = TemporaryDirectory('_ebook_iter') self._tdir = TemporaryDirectory('_ebook_iter')
self.base = self._tdir.__enter__() self.base = self._tdir.__enter__()
@ -116,50 +116,50 @@ class EbookIterator(object):
self.pathtoopf = self.to_opf(self.pathtoebook, self.base, opts) self.pathtoopf = self.to_opf(self.pathtoebook, self.base, opts)
self.opf = OPF(self.pathtoopf, os.path.dirname(self.pathtoopf)) self.opf = OPF(self.pathtoopf, os.path.dirname(self.pathtoopf))
self.spine = [SpineItem(i.path) for i in self.opf.spine] self.spine = [SpineItem(i.path) for i in self.opf.spine]
cover = self.opf.cover cover = self.opf.cover
if os.path.splitext(self.pathtoebook)[1].lower() in \ if os.path.splitext(self.pathtoebook)[1].lower() in \
('.lit', '.mobi', '.prc') and cover: ('.lit', '.mobi', '.prc') and cover:
cfile = os.path.join(os.path.dirname(self.spine[0]), 'calibre_ei_cover.html') cfile = os.path.join(os.path.dirname(self.spine[0]), 'calibre_ei_cover.html')
open(cfile, 'wb').write(TITLEPAGE%cover) open(cfile, 'wb').write(TITLEPAGE%cover)
self.spine[0:0] = [SpineItem(cfile)] self.spine[0:0] = [SpineItem(cfile)]
if self.opf.path_to_html_toc is not None and \ if self.opf.path_to_html_toc is not None and \
self.opf.path_to_html_toc not in self.spine: self.opf.path_to_html_toc not in self.spine:
self.spine.append(SpineItem(self.opf.path_to_html_toc)) self.spine.append(SpineItem(self.opf.path_to_html_toc))
sizes = [i.character_count for i in self.spine] sizes = [i.character_count for i in self.spine]
self.pages = [math.ceil(i/float(self.CHARACTERS_PER_PAGE)) for i in sizes] self.pages = [math.ceil(i/float(self.CHARACTERS_PER_PAGE)) for i in sizes]
for p, s in zip(self.pages, self.spine): for p, s in zip(self.pages, self.spine):
s.pages = p s.pages = p
start = 1 start = 1
for s in self.spine: for s in self.spine:
s.start_page = start s.start_page = start
start += s.pages start += s.pages
s.max_page = s.start_page + s.pages - 1 s.max_page = s.start_page + s.pages - 1
self.toc = self.opf.toc self.toc = self.opf.toc
self.find_embedded_fonts() self.find_embedded_fonts()
self.read_bookmarks() self.read_bookmarks()
return self return self
def parse_bookmarks(self, raw): def parse_bookmarks(self, raw):
for line in raw.splitlines(): for line in raw.splitlines():
if line.count('^') > 0: if line.count('^') > 0:
tokens = line.rpartition('^') tokens = line.rpartition('^')
title, ref = tokens[0], tokens[2] title, ref = tokens[0], tokens[2]
self.bookmarks.append((title, ref)) self.bookmarks.append((title, ref))
def serialize_bookmarks(self, bookmarks): def serialize_bookmarks(self, bookmarks):
dat = [] dat = []
for title, bm in bookmarks: for title, bm in bookmarks:
dat.append(u'%s^%s'%(title, bm)) dat.append(u'%s^%s'%(title, bm))
return (u'\n'.join(dat) +'\n').encode('utf-8') return (u'\n'.join(dat) +'\n').encode('utf-8')
def read_bookmarks(self): def read_bookmarks(self):
self.bookmarks = [] self.bookmarks = []
bmfile = os.path.join(self.base, 'META-INF', 'calibre_bookmarks.txt') bmfile = os.path.join(self.base, 'META-INF', 'calibre_bookmarks.txt')
@ -170,8 +170,8 @@ class EbookIterator(object):
saved = self.config['bookmarks_'+self.pathtoebook] saved = self.config['bookmarks_'+self.pathtoebook]
if saved: if saved:
raw = saved raw = saved
self.parse_bookmarks(raw) self.parse_bookmarks(raw)
def save_bookmarks(self, bookmarks=None): def save_bookmarks(self, bookmarks=None):
if bookmarks is None: if bookmarks is None:
bookmarks = self.bookmarks bookmarks = self.bookmarks
@ -190,7 +190,7 @@ class EbookIterator(object):
zipf.writestr('META-INF/calibre_bookmarks.txt', dat) zipf.writestr('META-INF/calibre_bookmarks.txt', dat)
else: else:
self.config['bookmarks_'+self.pathtoebook] = dat self.config['bookmarks_'+self.pathtoebook] = dat
def add_bookmark(self, bm): def add_bookmark(self, bm):
dups = [] dups = []
for x in self.bookmarks: for x in self.bookmarks:
@ -200,6 +200,6 @@ class EbookIterator(object):
self.bookmarks.remove(x) self.bookmarks.remove(x)
self.bookmarks.append(bm) self.bookmarks.append(bm)
self.save_bookmarks() self.save_bookmarks()
def __exit__(self, *args): def __exit__(self, *args):
self._tdir.__exit__(*args) self._tdir.__exit__(*args)