mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement recursive import assuming multiple ebooks per directory
This commit is contained in:
parent
8b97bb79f7
commit
c7cd76bdc7
@ -49,6 +49,12 @@ def get_metadata(stream, stream_type='lrf', use_libprs_metadata=False):
|
||||
if not base.authors:
|
||||
base.authors = ['Unknown']
|
||||
base.smart_update(mi)
|
||||
if hasattr(stream, 'name'):
|
||||
opfpath = os.path.abspath(os.path.splitext(stream.name)[0]+'.opf')
|
||||
if os.access(opfpath, os.R_OK):
|
||||
mi = opf_metadata(opfpath)
|
||||
if mi is not None:
|
||||
base.smart_update(mi)
|
||||
return base
|
||||
|
||||
def set_metadata(stream, mi, stream_type='lrf'):
|
||||
@ -104,18 +110,14 @@ def metadata_from_filename(name, pat=None):
|
||||
mi.title = name
|
||||
return mi
|
||||
|
||||
def libprs_metadata(name):
|
||||
if os.path.basename(name) != 'metadata.opf':
|
||||
name = os.path.join(os.path.dirname(name), 'metadata.opf')
|
||||
name = os.path.abspath(name)
|
||||
if os.access(name, os.R_OK):
|
||||
f = open(name, 'rb')
|
||||
opf = OPFReader(f, os.path.dirname(name))
|
||||
def opf_metadata(opfpath):
|
||||
f = open(opfpath, 'rb')
|
||||
opf = OPFReader(f, os.path.dirname(opfpath))
|
||||
try:
|
||||
if opf.libprs_id is not None:
|
||||
mi = MetaInformation(opf, None)
|
||||
if hasattr(opf, 'cover') and opf.cover:
|
||||
cpath = os.path.join(os.path.dirname(name), opf.cover)
|
||||
cpath = os.path.join(os.path.dirname(opfpath), opf.cover)
|
||||
if os.access(cpath, os.R_OK):
|
||||
fmt = cpath.rpartition('.')[-1]
|
||||
data = open(cpath, 'rb').read()
|
||||
@ -123,3 +125,12 @@ def libprs_metadata(name):
|
||||
return mi
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def libprs_metadata(name):
|
||||
if os.path.basename(name) != 'metadata.opf':
|
||||
name = os.path.join(os.path.dirname(name), 'metadata.opf')
|
||||
name = os.path.abspath(name)
|
||||
if os.access(name, os.R_OK):
|
||||
return opf_metadata(name)
|
||||
|
@ -120,11 +120,13 @@ class Main(MainWindow, Ui_MainWindow):
|
||||
self.metadata_menu = md
|
||||
self.add_menu = QMenu()
|
||||
self.add_menu.addAction(_('Add books from a single directory'))
|
||||
self.add_menu.addAction(_('Add books recursively (One book per directory)'))
|
||||
self.add_menu.addAction(_('Add books recursively (One book per directory, assumes every ebook file is the same book in a different format)'))
|
||||
self.add_menu.addAction(_('Add books recursively (Multiple books per directory, assumes every ebook file is a different book)'))
|
||||
self.action_add.setMenu(self.add_menu)
|
||||
QObject.connect(self.action_add, SIGNAL("triggered(bool)"), self.add_books)
|
||||
QObject.connect(self.add_menu.actions()[0], SIGNAL("triggered(bool)"), self.add_books)
|
||||
QObject.connect(self.add_menu.actions()[1], SIGNAL("triggered(bool)"), self.add_recursive_single)
|
||||
QObject.connect(self.add_menu.actions()[2], SIGNAL("triggered(bool)"), self.add_recursive_multiple)
|
||||
QObject.connect(self.action_del, SIGNAL("triggered(bool)"), self.delete_books)
|
||||
QObject.connect(self.action_edit, SIGNAL("triggered(bool)"), self.edit_metadata)
|
||||
QObject.connect(md.actions()[0], SIGNAL('triggered(bool)'), self.edit_metadata)
|
||||
@ -294,15 +296,11 @@ class Main(MainWindow, Ui_MainWindow):
|
||||
|
||||
################################# Add books ################################
|
||||
|
||||
def add_recursive_single(self, checked):
|
||||
'''
|
||||
Add books from the local filesystem to either the library or the device
|
||||
recursively assuming one book per folder.
|
||||
'''
|
||||
def add_recursive(self, single):
|
||||
root = choose_dir(self, 'recursive book import root dir dialog', 'Select root folder')
|
||||
if not root:
|
||||
return
|
||||
duplicates = self.library_view.model().db.recursive_import(root)
|
||||
duplicates = self.library_view.model().db.recursive_import(root, single)
|
||||
|
||||
if duplicates:
|
||||
files = _('<p>Books with the same title as the following already exist in the database. Add them anyway?<ul>')
|
||||
@ -316,6 +314,22 @@ class Main(MainWindow, Ui_MainWindow):
|
||||
self.library_view.model().resort()
|
||||
self.library_view.model().research()
|
||||
|
||||
def add_recursive_single(self, checked):
|
||||
'''
|
||||
Add books from the local filesystem to either the library or the device
|
||||
recursively assuming one book per folder.
|
||||
'''
|
||||
self.add_recursive(True)
|
||||
|
||||
def add_recursive_multiple(self, checked):
|
||||
'''
|
||||
Add books from the local filesystem to either the library or the device
|
||||
recursively assuming multiple books per folder.
|
||||
'''
|
||||
self.add_recursive(False)
|
||||
|
||||
|
||||
|
||||
|
||||
def add_books(self, checked):
|
||||
'''
|
||||
|
@ -1355,6 +1355,42 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
||||
f.close()
|
||||
|
||||
|
||||
def import_book_directory_multiple(self, dirpath, add_duplicates=False):
|
||||
mi = MetaInformation(None, None)
|
||||
dirpath = os.path.abspath(dirpath)
|
||||
duplicates = []
|
||||
for path in os.listdir(dirpath):
|
||||
path = os.path.join(dirpath, path)
|
||||
if os.path.isdir(path) or not os.access(path, os.R_OK):
|
||||
continue
|
||||
ext = os.path.splitext(path)[1]
|
||||
if not ext:
|
||||
continue
|
||||
ext = ext[1:].lower()
|
||||
if ext not in BOOK_EXTENSIONS:
|
||||
continue
|
||||
stream = open(path, 'rb')
|
||||
mi.smart_update(get_metadata(stream, stream_type=ext, use_libprs_metadata=False))
|
||||
if mi.title is None:
|
||||
continue
|
||||
if not add_duplicates and self.conn.execute('SELECT id FROM books where title=?', (mi.title,)).fetchone():
|
||||
duplicates.append((mi, path))
|
||||
continue
|
||||
series_index = 1 if mi.series_index is None else mi.series_index
|
||||
obj = self.conn.execute('INSERT INTO books(title, uri, series_index) VALUES (?, ?, ?)',
|
||||
(mi.title, None, series_index))
|
||||
id = obj.lastrowid
|
||||
self.conn.commit()
|
||||
self.set_metadata(id, mi)
|
||||
stream.seek(0, 2)
|
||||
usize = stream.tell()
|
||||
stream.seek(0)
|
||||
self.conn.execute('INSERT INTO data(book, format, uncompressed_size, data) VALUES (?,?,?,?)',
|
||||
(id, ext, usize, sqlite.Binary(compress(stream.read()))))
|
||||
self.conn.commit()
|
||||
return duplicates
|
||||
|
||||
|
||||
def import_book_directory(self, dirpath, add_duplicates=False):
|
||||
mi = MetaInformation(None, None)
|
||||
dirpath = os.path.abspath(dirpath)
|
||||
@ -1371,6 +1407,7 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
||||
continue
|
||||
f = open(path, 'rb')
|
||||
mi.smart_update(get_metadata(f, stream_type=ext, use_libprs_metadata=True))
|
||||
f.close()
|
||||
formats.append((ext, path))
|
||||
if mi.title is None or not formats:
|
||||
return
|
||||
@ -1392,13 +1429,16 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
||||
self.conn.commit()
|
||||
|
||||
|
||||
def recursive_import(self, root):
|
||||
def recursive_import(self, root, single_book_per_directory=True):
|
||||
root = os.path.abspath(root)
|
||||
duplicates = []
|
||||
for dirpath in os.walk(root):
|
||||
res = self.import_book_directory(dirpath[0])
|
||||
res = self.import_book_directory(dirpath[0]) if single_book_per_directory else self.import_book_directory_multiple(dirpath[0])
|
||||
if res is not None:
|
||||
if single_book_per_directory:
|
||||
duplicates.append(res)
|
||||
else:
|
||||
duplicates.extend(res)
|
||||
return duplicates
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user