mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Add a callback to FileTypePlugins that is useful for modifying the book record in the database when it is first created
This commit is contained in:
parent
8fce6f04ef
commit
c956a64aa3
@ -179,8 +179,7 @@ class Plugin(object): # {{{
|
||||
help_text = self.customization_help(gui=True)
|
||||
help_text = QLabel(help_text, config_dialog)
|
||||
help_text.setWordWrap(True)
|
||||
help_text.setTextInteractionFlags(Qt.LinksAccessibleByMouse
|
||||
| Qt.LinksAccessibleByKeyboard)
|
||||
help_text.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard)
|
||||
help_text.setOpenExternalLinks(True)
|
||||
v.addWidget(help_text)
|
||||
sc = plugin_customization(self)
|
||||
@ -369,6 +368,21 @@ class FileTypePlugin(Plugin): # {{{
|
||||
'''
|
||||
pass # Default implementation does nothing
|
||||
|
||||
def postadd(self, book_id, fmt_map, db):
|
||||
'''
|
||||
Called post add, i.e. after a book has been added to the db. Note that
|
||||
this is different from :meth:`postimport`, which is called after a single book file
|
||||
has been added to a book. postadd() is called only when an entire book record
|
||||
with possibly more than one book file has been created for the first time.
|
||||
This is useful if you wish to modify the book record in the database when the
|
||||
book is first added to calibre.
|
||||
|
||||
:param book_id: Database id of the added book.
|
||||
:param fmt_map: Map of file format to path from which the file format was added
|
||||
:param db: Library database
|
||||
'''
|
||||
pass # Default implementation does nothing
|
||||
|
||||
# }}}
|
||||
|
||||
class MetadataReaderPlugin(Plugin): # {{{
|
||||
|
@ -3,6 +3,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
import os, shutil, traceback, functools, sys
|
||||
from collections import defaultdict
|
||||
|
||||
from calibre.customize import (CatalogPlugin, FileTypePlugin, PluginNotFound,
|
||||
MetadataReaderPlugin, MetadataWriterPlugin,
|
||||
@ -44,7 +45,7 @@ def find_plugin(name):
|
||||
return plugin
|
||||
|
||||
|
||||
def load_plugin(path_to_zip_file): # {{{
|
||||
def load_plugin(path_to_zip_file): # {{{
|
||||
'''
|
||||
Load plugin from zip file or raise InvalidPlugin error
|
||||
|
||||
@ -95,7 +96,8 @@ default_disabled_plugins = set([
|
||||
])
|
||||
|
||||
def is_disabled(plugin):
|
||||
if plugin.name in config['enabled_plugins']: return False
|
||||
if plugin.name in config['enabled_plugins']:
|
||||
return False
|
||||
return plugin.name in config['disabled_plugins'] or \
|
||||
plugin.name in default_disabled_plugins
|
||||
# }}}
|
||||
@ -106,35 +108,30 @@ _on_import = {}
|
||||
_on_postimport = {}
|
||||
_on_preprocess = {}
|
||||
_on_postprocess = {}
|
||||
_on_postadd = []
|
||||
|
||||
def reread_filetype_plugins():
|
||||
global _on_import
|
||||
global _on_postimport
|
||||
global _on_preprocess
|
||||
global _on_postprocess
|
||||
_on_import = {}
|
||||
_on_postimport = {}
|
||||
_on_preprocess = {}
|
||||
_on_postprocess = {}
|
||||
_on_import = defaultdict(list)
|
||||
_on_postimport = defaultdict(list)
|
||||
_on_preprocess = defaultdict(list)
|
||||
_on_postprocess = defaultdict(list)
|
||||
_on_postadd = []
|
||||
|
||||
for plugin in _initialized_plugins:
|
||||
if isinstance(plugin, FileTypePlugin):
|
||||
for ft in plugin.file_types:
|
||||
if plugin.on_import:
|
||||
if not _on_import.has_key(ft):
|
||||
_on_import[ft] = []
|
||||
_on_import[ft].append(plugin)
|
||||
if plugin.on_postimport:
|
||||
if not _on_postimport.has_key(ft):
|
||||
_on_postimport[ft] = []
|
||||
_on_postimport[ft].append(plugin)
|
||||
_on_postadd.append(plugin)
|
||||
if plugin.on_preprocess:
|
||||
if not _on_preprocess.has_key(ft):
|
||||
_on_preprocess[ft] = []
|
||||
_on_preprocess[ft].append(plugin)
|
||||
if plugin.on_postprocess:
|
||||
if not _on_postprocess.has_key(ft):
|
||||
_on_postprocess[ft] = []
|
||||
_on_postprocess[ft].append(plugin)
|
||||
|
||||
|
||||
@ -187,6 +184,20 @@ def run_plugins_on_postimport(db, book_id, fmt):
|
||||
plugin.name)
|
||||
traceback.print_exc()
|
||||
|
||||
def run_plugins_on_postadd(db, book_id, fmt_map):
|
||||
customization = config['plugin_customization']
|
||||
for plugin in _on_postadd:
|
||||
if is_disabled(plugin):
|
||||
continue
|
||||
plugin.site_customization = customization.get(plugin.name, '')
|
||||
with plugin:
|
||||
try:
|
||||
plugin.postadd(book_id, fmt_map, db)
|
||||
except Exception:
|
||||
print ('Running file type plugin %s failed with traceback:'%
|
||||
plugin.name)
|
||||
traceback.print_exc()
|
||||
|
||||
# }}}
|
||||
|
||||
# Plugin customization {{{
|
||||
@ -268,17 +279,14 @@ _metadata_writers = {}
|
||||
def reread_metadata_plugins():
|
||||
global _metadata_readers
|
||||
global _metadata_writers
|
||||
_metadata_readers = {}
|
||||
_metadata_readers = defaultdict(list)
|
||||
_metadata_writers = defaultdict(list)
|
||||
for plugin in _initialized_plugins:
|
||||
if isinstance(plugin, MetadataReaderPlugin):
|
||||
for ft in plugin.file_types:
|
||||
if not _metadata_readers.has_key(ft):
|
||||
_metadata_readers[ft] = []
|
||||
_metadata_readers[ft].append(plugin)
|
||||
elif isinstance(plugin, MetadataWriterPlugin):
|
||||
for ft in plugin.file_types:
|
||||
if not _metadata_writers.has_key(ft):
|
||||
_metadata_writers[ft] = []
|
||||
_metadata_writers[ft].append(plugin)
|
||||
|
||||
def metadata_readers():
|
||||
@ -338,7 +346,7 @@ def get_file_type_metadata(stream, ftype):
|
||||
mi = MetaInformation(None, None)
|
||||
|
||||
ftype = ftype.lower().strip()
|
||||
if _metadata_readers.has_key(ftype):
|
||||
if ftype in _metadata_readers:
|
||||
for plugin in _metadata_readers[ftype]:
|
||||
if not is_disabled(plugin):
|
||||
with plugin:
|
||||
@ -355,7 +363,7 @@ def get_file_type_metadata(stream, ftype):
|
||||
|
||||
def set_file_type_metadata(stream, mi, ftype, report_error=None):
|
||||
ftype = ftype.lower().strip()
|
||||
if _metadata_writers.has_key(ftype):
|
||||
if ftype in _metadata_writers:
|
||||
for plugin in _metadata_writers[ftype]:
|
||||
if not is_disabled(plugin):
|
||||
with plugin:
|
||||
@ -708,4 +716,3 @@ def main(args=sys.argv):
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
# }}}
|
||||
|
||||
|
@ -15,7 +15,7 @@ from future_builtins import zip
|
||||
|
||||
from calibre import isbytestring, as_unicode
|
||||
from calibre.constants import iswindows, preferred_encoding
|
||||
from calibre.customize.ui import run_plugins_on_import, run_plugins_on_postimport
|
||||
from calibre.customize.ui import run_plugins_on_import, run_plugins_on_postimport, run_plugins_on_postadd
|
||||
from calibre.db import SPOOL_SIZE, _get_next_series_num_for_list
|
||||
from calibre.db.categories import get_categories
|
||||
from calibre.db.locking import create_locks, DowngradeLockError, SafeReadLock
|
||||
@ -1544,6 +1544,7 @@ class Cache(object):
|
||||
as per the simple duplicate detection heuristic used by :meth:`has_book`.
|
||||
'''
|
||||
duplicates, ids = [], []
|
||||
fmt_map = {}
|
||||
for mi, format_map in books:
|
||||
book_id = self.create_book_entry(mi, add_duplicates=add_duplicates, apply_import_tags=apply_import_tags, preserve_uuid=preserve_uuid)
|
||||
if book_id is None:
|
||||
@ -1551,7 +1552,9 @@ class Cache(object):
|
||||
else:
|
||||
ids.append(book_id)
|
||||
for fmt, stream_or_path in format_map.iteritems():
|
||||
self.add_format(book_id, fmt, stream_or_path, dbapi=dbapi, run_hooks=run_hooks)
|
||||
if self.add_format(book_id, fmt, stream_or_path, dbapi=dbapi, run_hooks=run_hooks):
|
||||
fmt_map[fmt.lower()] = getattr(stream_or_path, 'name', stream_or_path) or '<stream>'
|
||||
run_plugins_on_postadd(dbapi or self, book_id, fmt_map)
|
||||
return ids, duplicates
|
||||
|
||||
@write_api
|
||||
|
@ -16,7 +16,7 @@ from PyQt5.Qt import QObject, Qt, pyqtSignal
|
||||
|
||||
from calibre import prints, as_unicode
|
||||
from calibre.constants import DEBUG
|
||||
from calibre.customize.ui import run_plugins_on_postimport
|
||||
from calibre.customize.ui import run_plugins_on_postimport, run_plugins_on_postadd
|
||||
from calibre.db.adding import find_books_in_directory
|
||||
from calibre.db.utils import find_identical_books
|
||||
from calibre.ebooks.metadata.book.base import Metadata
|
||||
@ -375,7 +375,7 @@ class Adder(QObject):
|
||||
[a('\t' + f) for f in paths]
|
||||
a(_('With error:')), a(traceback.format_exc())
|
||||
return
|
||||
self.add_formats(book_id, paths, mi)
|
||||
self.add_formats(book_id, paths, mi, is_an_add=True)
|
||||
try:
|
||||
if self.add_formats_to_existing:
|
||||
self.db.update_data_for_find_identical_books(book_id, self.find_identical_books_data)
|
||||
@ -388,8 +388,9 @@ class Adder(QObject):
|
||||
if DEBUG:
|
||||
prints('Added', mi.title, 'to db in: %.1f' % (time.time() - st))
|
||||
|
||||
def add_formats(self, book_id, paths, mi, replace=True):
|
||||
def add_formats(self, book_id, paths, mi, replace=True, is_an_add=False):
|
||||
fmap = {p.rpartition(os.path.extsep)[-1].lower():p for p in paths}
|
||||
fmt_map = {}
|
||||
for fmt, path in fmap.iteritems():
|
||||
# The onimport plugins have already been run by the read metadata
|
||||
# worker
|
||||
@ -398,11 +399,14 @@ class Adder(QObject):
|
||||
try:
|
||||
if self.db.add_format(book_id, fmt, path, run_hooks=False, replace=replace):
|
||||
run_plugins_on_postimport(self.dbref(), book_id, fmt)
|
||||
fmt_map[fmt.lower()] = path
|
||||
except Exception:
|
||||
a = self.report.append
|
||||
a(''), a('-' * 70)
|
||||
a(_('Failed to add the file {0} to the book: {1}').format(path, mi.title))
|
||||
a(_('With error:')), a(traceback.format_exc())
|
||||
if is_an_add:
|
||||
run_plugins_on_postadd(self.dbref(), book_id, fmt_map)
|
||||
|
||||
def process_duplicates(self):
|
||||
if self.duplicates:
|
||||
|
Loading…
x
Reference in New Issue
Block a user