Add progress indication when adding books to the library

This commit is contained in:
Kovid Goyal 2008-12-23 22:25:13 -08:00
parent 660fa430f8
commit 5769ce558c
2 changed files with 91 additions and 47 deletions

View File

@ -6,7 +6,8 @@ from functools import partial
from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, QUrl, QTimer from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, QUrl, QTimer
from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox, \ from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox, \
QToolButton, QDialog, QDesktopServices, QFileDialog, \ QToolButton, QDialog, QDesktopServices, QFileDialog, \
QSystemTrayIcon, QApplication, QKeySequence, QAction QSystemTrayIcon, QApplication, QKeySequence, QAction, \
QProgressDialog
from PyQt4.QtSvg import QSvgRenderer from PyQt4.QtSvg import QSvgRenderer
from calibre import __version__, __appname__, islinux, sanitize_file_name, \ from calibre import __version__, __appname__, islinux, sanitize_file_name, \
@ -566,8 +567,23 @@ class Main(MainWindow, Ui_MainWindow):
root = choose_dir(self, 'recursive book import root dir dialog', 'Select root folder') root = choose_dir(self, 'recursive book import root dir dialog', 'Select root folder')
if not root: if not root:
return return
duplicates = self.library_view.model().db.recursive_import(root, single) progress = QProgressDialog('', '&'+_('Stop'),
0, 0, self)
progress.setWindowModality(Qt.ApplicationModal)
progress.setWindowTitle(_('Adding books recursively...'))
progress.show()
def callback(msg):
if msg != '.':
progress.setLabelText((_('Added ')+msg) if msg else _('Searching...'))
stop = progress.wasCanceled()
QApplication.processEvents()
QApplication.sendPostedEvents()
QApplication.flush()
return stop
try:
duplicates = self.library_view.model().db.recursive_import(root, single, callback=callback)
finally:
progress.close()
if duplicates: if duplicates:
files = _('<p>Books with the same title as the following already exist in the database. Add them anyway?<ul>') files = _('<p>Books with the same title as the following already exist in the database. Add them anyway?<ul>')
for mi, formats in duplicates: for mi, formats in duplicates:
@ -634,49 +650,61 @@ class Main(MainWindow, Ui_MainWindow):
def _add_books(self, paths, to_device, on_card=None): def _add_books(self, paths, to_device, on_card=None):
if on_card is None: if on_card is None:
on_card = self.stack.currentIndex() == 2 on_card = self.stack.currentIndex() == 2
if not paths:
return
# Get format and metadata information # Get format and metadata information
formats, metadata, names, infos = [], [], [], [] formats, metadata, names, infos = [], [], [], []
for book in paths: progress = QProgressDialog(_('Reading metadata...'), _('Stop'), 0, len(paths), self)
format = os.path.splitext(book)[1] progress.setWindowTitle(_('Adding books...'))
format = format[1:] if format else None progress.setWindowModality(Qt.ApplicationModal)
stream = open(book, 'rb') progress.setLabelText(_('Reading metadata...'))
try: progress.show()
mi = get_metadata(stream, stream_type=format, use_libprs_metadata=True) try:
except: for c, book in enumerate(paths):
mi = MetaInformation(None, None) progress.setValue(c)
if not mi.title: if progress.wasCanceled():
mi.title = os.path.splitext(os.path.basename(book))[0] return
if not mi.authors: format = os.path.splitext(book)[1]
mi.authors = [_('Unknown')] format = format[1:] if format else None
formats.append(format) stream = open(book, 'rb')
metadata.append(mi) try:
names.append(os.path.basename(book)) mi = get_metadata(stream, stream_type=format, use_libprs_metadata=True)
infos.append({'title':mi.title, 'authors':', '.join(mi.authors), except:
'cover':self.default_thumbnail, 'tags':[]}) mi = MetaInformation(None, None)
if not mi.title:
if not to_device: mi.title = os.path.splitext(os.path.basename(book))[0]
model = self.library_view.model() if not mi.authors:
mi.authors = [_('Unknown')]
formats.append(format)
metadata.append(mi)
names.append(os.path.basename(book))
infos.append({'title':mi.title, 'authors':', '.join(mi.authors),
'cover':self.default_thumbnail, 'tags':[]})
title = mi.title if isinstance(mi.title, unicode) else mi.title.decode(preferred_encoding, 'replace')
progress.setLabelText(_('Read metadata from ')+title)
paths = list(paths) if not to_device:
#for i, path in enumerate(paths): progress.setLabelText(_('Adding books to database...'))
# npath, fmt = import_format(path) model = self.library_view.model()
# if npath is not None:
# paths[i] = npath paths = list(paths)
# formats[i] = fmt duplicates, number_added = model.add_books(paths, formats, metadata)
duplicates, number_added = model.add_books(paths, formats, metadata) progress.cancel()
if duplicates: if duplicates:
files = _('<p>Books with the same title as the following already exist in the database. Add them anyway?<ul>') files = _('<p>Books with the same title as the following already exist in the database. Add them anyway?<ul>')
for mi in duplicates[2]: for mi in duplicates[2]:
files += '<li>'+mi.title+'</li>\n' files += '<li>'+mi.title+'</li>\n'
d = WarningDialog(_('Duplicates found!'), _('Duplicates found!'), files+'</ul></p>', parent=self) d = WarningDialog(_('Duplicates found!'), _('Duplicates found!'), files+'</ul></p>', parent=self)
if d.exec_() == QDialog.Accepted: if d.exec_() == QDialog.Accepted:
num = model.add_books(*duplicates, **dict(add_duplicates=True))[1] num = model.add_books(*duplicates, **dict(add_duplicates=True))[1]
number_added += num number_added += num
#self.library_view.sortByColumn(3, Qt.DescendingOrder) #self.library_view.sortByColumn(3, Qt.DescendingOrder)
#model.research() #model.research()
model.books_added(number_added) model.books_added(number_added)
else: else:
self.upload_books(paths, list(map(sanitize_file_name, names)), infos, on_card=on_card) self.upload_books(paths, list(map(sanitize_file_name, names)), infos, on_card=on_card)
finally:
progress.setValue(len(paths))
def upload_books(self, files, names, metadata, on_card=False, memory=None): def upload_books(self, files, names, metadata, on_card=False, memory=None):
''' '''

View File

@ -1471,11 +1471,13 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
(usize, data, id, ext)) (usize, data, id, ext))
self.conn.commit() self.conn.commit()
def import_book_directory_multiple(self, dirpath): def import_book_directory_multiple(self, dirpath, callback=None):
dirpath = os.path.abspath(dirpath) dirpath = os.path.abspath(dirpath)
duplicates = [] duplicates = []
books = {} books = {}
for path in os.listdir(dirpath): for path in os.listdir(dirpath):
if callable(callback):
callback('.')
path = os.path.abspath(os.path.join(dirpath, path)) path = os.path.abspath(os.path.join(dirpath, path))
if os.path.isdir(path) or not os.access(path, os.R_OK): if os.path.isdir(path) or not os.access(path, os.R_OK):
continue continue
@ -1500,13 +1502,18 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
duplicates.append((mi, formats)) duplicates.append((mi, formats))
continue continue
self.import_book(mi, formats) self.import_book(mi, formats)
if callable(callback):
if callback(mi.title):
break
return duplicates return duplicates
def import_book_directory(self, dirpath): def import_book_directory(self, dirpath, callback=None):
dirpath = os.path.abspath(dirpath) dirpath = os.path.abspath(dirpath)
formats = [] formats = []
for path in os.listdir(dirpath): for path in os.listdir(dirpath):
if callable(callback):
callback('.')
path = os.path.abspath(os.path.join(dirpath, path)) path = os.path.abspath(os.path.join(dirpath, path))
if os.path.isdir(path) or not os.access(path, os.R_OK): if os.path.isdir(path) or not os.access(path, os.R_OK):
continue continue
@ -1527,6 +1534,9 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
if self.has_book(mi): if self.has_book(mi):
return [(mi, formats)] return [(mi, formats)]
self.import_book(mi, formats) self.import_book(mi, formats)
if callable(callback):
callback(mi.title)
def has_book(self, mi): def has_book(self, mi):
@ -1535,13 +1545,19 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
def has_id(self, id): def has_id(self, id):
return self.conn.get('SELECT id FROM books where id=?', (id,), all=False) is not None return self.conn.get('SELECT id FROM books where id=?', (id,), all=False) is not None
def recursive_import(self, root, single_book_per_directory=True): def recursive_import(self, root, single_book_per_directory=True, callback=None):
root = os.path.abspath(root) root = os.path.abspath(root)
duplicates = [] duplicates = []
for dirpath in os.walk(root): for dirpath in os.walk(root):
res = self.import_book_directory(dirpath[0]) if single_book_per_directory else self.import_book_directory_multiple(dirpath[0]) res = self.import_book_directory(dirpath[0], callback=callback) if \
single_book_per_directory else \
self.import_book_directory_multiple(dirpath[0], callback=callback)
if res is not None: if res is not None:
duplicates.extend(res) duplicates.extend(res)
if callable(callback):
if callback(''):
break
return duplicates return duplicates
def export_single_format_to_dir(self, dir, indices, format, index_is_id=False): def export_single_format_to_dir(self, dir, indices, format, index_is_id=False):