mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
IGN:Fix reading of epub metadata in non GUI threads
This commit is contained in:
parent
939963d366
commit
c50e47fdd8
@ -51,7 +51,7 @@ class OCF(object):
|
|||||||
MIMETYPE = 'application/epub+zip'
|
MIMETYPE = 'application/epub+zip'
|
||||||
CONTAINER_PATH = 'META-INF/container.xml'
|
CONTAINER_PATH = 'META-INF/container.xml'
|
||||||
ENCRYPTION_PATH = 'META-INF/encryption.xml'
|
ENCRYPTION_PATH = 'META-INF/encryption.xml'
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
raise NotImplementedError('Abstract base class')
|
raise NotImplementedError('Abstract base class')
|
||||||
|
|
||||||
@ -70,13 +70,13 @@ class OCFReader(OCF):
|
|||||||
self.container = Container(f)
|
self.container = Container(f)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise EPubException("missing OCF container.xml file")
|
raise EPubException("missing OCF container.xml file")
|
||||||
self.opf_path = self.container[OPF.MIMETYPE]
|
self.opf_path = self.container[OPF.MIMETYPE]
|
||||||
try:
|
try:
|
||||||
with closing(self.open(self.opf_path)) as f:
|
with closing(self.open(self.opf_path)) as f:
|
||||||
self.opf = OPF(f, self.root)
|
self.opf = OPF(f, self.root)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise EPubException("missing OPF package file")
|
raise EPubException("missing OPF package file")
|
||||||
|
|
||||||
|
|
||||||
class OCFZipReader(OCFReader):
|
class OCFZipReader(OCFReader):
|
||||||
def __init__(self, stream, mode='r', root=None):
|
def __init__(self, stream, mode='r', root=None):
|
||||||
@ -93,19 +93,19 @@ class OCFZipReader(OCFReader):
|
|||||||
|
|
||||||
def open(self, name, mode='r'):
|
def open(self, name, mode='r'):
|
||||||
return StringIO(self.archive.read(name))
|
return StringIO(self.archive.read(name))
|
||||||
|
|
||||||
class OCFDirReader(OCFReader):
|
class OCFDirReader(OCFReader):
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
self.root = path
|
self.root = path
|
||||||
super(OCFDirReader, self).__init__()
|
super(OCFDirReader, self).__init__()
|
||||||
|
|
||||||
def open(self, path, *args, **kwargs):
|
def open(self, path, *args, **kwargs):
|
||||||
return open(os.path.join(self.root, path), *args, **kwargs)
|
return open(os.path.join(self.root, path), *args, **kwargs)
|
||||||
|
|
||||||
class CoverRenderer(QObject):
|
class CoverRenderer(QObject):
|
||||||
WIDTH = 600
|
WIDTH = 600
|
||||||
HEIGHT = 800
|
HEIGHT = 800
|
||||||
|
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
if QApplication.instance() is None:
|
if QApplication.instance() is None:
|
||||||
QApplication([])
|
QApplication([])
|
||||||
@ -123,7 +123,7 @@ class CoverRenderer(QObject):
|
|||||||
self.rendered = False
|
self.rendered = False
|
||||||
url = QUrl.fromLocalFile(os.path.normpath(path))
|
url = QUrl.fromLocalFile(os.path.normpath(path))
|
||||||
self.page.mainFrame().load(url)
|
self.page.mainFrame().load(url)
|
||||||
|
|
||||||
def render_html(self, ok):
|
def render_html(self, ok):
|
||||||
try:
|
try:
|
||||||
if not ok:
|
if not ok:
|
||||||
@ -158,6 +158,8 @@ class CoverRenderer(QObject):
|
|||||||
|
|
||||||
|
|
||||||
def get_cover(opf, opf_path, stream):
|
def get_cover(opf, opf_path, stream):
|
||||||
|
from calibre.gui2 import is_ok_to_use_qt
|
||||||
|
if not is_ok_to_use_qt(): return None
|
||||||
spine = list(opf.spine_items())
|
spine = list(opf.spine_items())
|
||||||
if not spine:
|
if not spine:
|
||||||
return
|
return
|
||||||
@ -172,7 +174,7 @@ def get_cover(opf, opf_path, stream):
|
|||||||
return
|
return
|
||||||
cr = CoverRenderer(cpage)
|
cr = CoverRenderer(cpage)
|
||||||
return cr.image_data
|
return cr.image_data
|
||||||
|
|
||||||
def get_metadata(stream, extract_cover=True):
|
def get_metadata(stream, extract_cover=True):
|
||||||
""" Return metadata as a :class:`MetaInformation` object """
|
""" Return metadata as a :class:`MetaInformation` object """
|
||||||
stream.seek(0)
|
stream.seek(0)
|
||||||
@ -194,11 +196,11 @@ def set_metadata(stream, mi):
|
|||||||
reader.opf.smart_update(mi)
|
reader.opf.smart_update(mi)
|
||||||
newopf = StringIO(reader.opf.render())
|
newopf = StringIO(reader.opf.render())
|
||||||
safe_replace(stream, reader.container[OPF.MIMETYPE], newopf)
|
safe_replace(stream, reader.container[OPF.MIMETYPE], newopf)
|
||||||
|
|
||||||
def option_parser():
|
def option_parser():
|
||||||
parser = get_parser('epub')
|
parser = get_parser('epub')
|
||||||
parser.remove_option('--category')
|
parser.remove_option('--category')
|
||||||
parser.add_option('--tags', default=None,
|
parser.add_option('--tags', default=None,
|
||||||
help=_('A comma separated list of tags to set'))
|
help=_('A comma separated list of tags to set'))
|
||||||
parser.add_option('--series', default=None,
|
parser.add_option('--series', default=None,
|
||||||
help=_('The series to which this book belongs'))
|
help=_('The series to which this book belongs'))
|
||||||
@ -240,17 +242,17 @@ def main(args=sys.argv):
|
|||||||
if opts.language is not None:
|
if opts.language is not None:
|
||||||
mi.language = opts.language
|
mi.language = opts.language
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
if changed:
|
if changed:
|
||||||
set_metadata(stream, mi)
|
set_metadata(stream, mi)
|
||||||
print unicode(get_metadata(stream, extract_cover=False)).encode('utf-8')
|
print unicode(get_metadata(stream, extract_cover=False)).encode('utf-8')
|
||||||
|
|
||||||
if mi.cover_data[1] is not None:
|
if mi.cover_data[1] is not None:
|
||||||
cpath = os.path.splitext(os.path.basename(args[1]))[0] + '_cover.jpg'
|
cpath = os.path.splitext(os.path.basename(args[1]))[0] + '_cover.jpg'
|
||||||
with open(cpath, 'wb') as f:
|
with open(cpath, 'wb') as f:
|
||||||
f.write(mi.cover_data[1])
|
f.write(mi.cover_data[1])
|
||||||
print 'Cover saved to', f.name
|
print 'Cover saved to', f.name
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -3,7 +3,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
""" The GUI """
|
""" The GUI """
|
||||||
import os
|
import os
|
||||||
from PyQt4.QtCore import QVariant, QFileInfo, QObject, SIGNAL, QBuffer, Qt, QSize, \
|
from PyQt4.QtCore import QVariant, QFileInfo, QObject, SIGNAL, QBuffer, Qt, QSize, \
|
||||||
QByteArray, QUrl, QTranslator, QCoreApplication
|
QByteArray, QUrl, QTranslator, QCoreApplication, QThread
|
||||||
from PyQt4.QtGui import QFileDialog, QMessageBox, QPixmap, QFileIconProvider, \
|
from PyQt4.QtGui import QFileDialog, QMessageBox, QPixmap, QFileIconProvider, \
|
||||||
QIcon, QTableView, QApplication, QDialog
|
QIcon, QTableView, QApplication, QDialog
|
||||||
|
|
||||||
@ -457,11 +457,14 @@ try:
|
|||||||
except:
|
except:
|
||||||
SingleApplication = None
|
SingleApplication = None
|
||||||
|
|
||||||
|
gui_thread = None
|
||||||
|
|
||||||
class Application(QApplication):
|
class Application(QApplication):
|
||||||
|
|
||||||
def __init__(self, args):
|
def __init__(self, args):
|
||||||
qargs = [i.encode('utf-8') if isinstance(i, unicode) else i for i in args]
|
qargs = [i.encode('utf-8') if isinstance(i, unicode) else i for i in args]
|
||||||
QApplication.__init__(self, qargs)
|
QApplication.__init__(self, qargs)
|
||||||
|
gui_thread = QThread.currentThread()
|
||||||
self.translator = QTranslator(self)
|
self.translator = QTranslator(self)
|
||||||
lang = get_lang()
|
lang = get_lang()
|
||||||
if lang:
|
if lang:
|
||||||
@ -470,3 +473,11 @@ class Application(QApplication):
|
|||||||
self.translator.loadFromData(data)
|
self.translator.loadFromData(data)
|
||||||
self.installTranslator(self.translator)
|
self.installTranslator(self.translator)
|
||||||
|
|
||||||
|
def is_ok_to_use_qt():
|
||||||
|
global gui_thread
|
||||||
|
if QApplication.instance() is None:
|
||||||
|
QApplication([])
|
||||||
|
if gui_thread is None:
|
||||||
|
gui_thread = QThread.currentThread()
|
||||||
|
return gui_thread is QThread.currentThread()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user