Implement recursive import assuming multiple ebooks per directory

This commit is contained in:
Kovid Goyal 2008-02-22 20:46:12 +00:00
parent 8b97bb79f7
commit c7cd76bdc7
3 changed files with 90 additions and 25 deletions

View File

@ -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)

View File

@ -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):
'''

View File

@ -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