Only accept non-user and non-network events while processing books.

This commit is contained in:
Charles Haley 2014-01-16 13:08:28 +01:00
parent 4b88f78bd0
commit 7aa33052ac

View File

@ -9,7 +9,7 @@ from threading import Thread, Event
from PyQt4.Qt import ( from PyQt4.Qt import (
QMenu, QAction, QActionGroup, QIcon, SIGNAL, Qt, pyqtSignal, QDialog, QMenu, QAction, QActionGroup, QIcon, SIGNAL, Qt, pyqtSignal, QDialog,
QObject, QVBoxLayout, QDialogButtonBox, QCursor, QCoreApplication, QObject, QVBoxLayout, QDialogButtonBox, QCursor, QCoreApplication,
QApplication) QApplication, QEventLoop)
from calibre.customize.ui import (available_input_formats, available_output_formats, from calibre.customize.ui import (available_input_formats, available_output_formats,
device_plugins, disabled_device_plugins) device_plugins, disabled_device_plugins)
@ -1790,93 +1790,101 @@ class DeviceMixin(object): # {{{
prints('DeviceJob: set_books_in_library: books to process=', total_book_count) prints('DeviceJob: set_books_in_library: books to process=', total_book_count)
start_time = time.time() start_time = time.time()
QApplication.setOverrideCursor(Qt.WaitCursor) QApplication.setOverrideCursor(Qt.WaitCursor)
current_book_count = 0; try:
for booklist in booklists: current_book_count = 0;
for book in booklist: for booklist in booklists:
if current_book_count % 100 == 0: for book in booklist:
self.status_bar.show_message( if current_book_count % 100 == 0:
_('Analyzing books on the device: %d%% finished')%( self.status_bar.show_message(
int((float(current_book_count)/total_book_count)*100.0))) _('Analyzing books on the device: %d%% finished')%(
int((float(current_book_count)/total_book_count)*100.0)))
# I am assuming that this pseudo multi-threading won't break # I am assuming that this sort-of multi-threading won't break
# anything. Reasons: UI actions that change the DB will happen # anything. Reasons: excluding UI events prevents the user
# synchronously with this loop, and the device booklist isn't # from explicitly changing anything, and (in theory) no
# used until this loop finishes. Of course, the UI will stutter # changes are happening because of timers and the like.
# somewhat, but that is better than locking up. Why every tenth # Why every tenth book? WAG balancing performance in the
# book? WAG balancing performance in the loop with the user # loop with preventing App Not Responding errors
# being able to get something done if current_book_count % 10 == 0:
if current_book_count % 10 == 0: QCoreApplication.processEvents(flags=
QCoreApplication.processEvents() QEventLoop.ExcludeUserInputEvents|
QEventLoop.ExcludeSocketNotifiers)
current_book_count += 1; time.sleep(0.01)
book.in_library = None current_book_count += 1;
if getattr(book, 'uuid', None) in self.db_book_uuid_cache: book.in_library = None
id_ = db_book_uuid_cache[book.uuid] if getattr(book, 'uuid', None) in self.db_book_uuid_cache:
if updateq(id_, book): id_ = db_book_uuid_cache[book.uuid]
update_book(id_, book) if updateq(id_, book):
book.in_library = 'UUID'
# ensure that the correct application_id is set
book.application_id = id_
continue
# No UUID exact match. Try metadata matching.
book_title = clean_string(book.title)
d = self.db_book_title_cache.get(book_title, None)
if d is not None:
# At this point we know that the title matches. The book
# will match if any of the db_id, author, or author_sort
# also match.
if getattr(book, 'application_id', None) in d['db_ids']:
id_ = getattr(book, 'application_id', None)
update_book(id_, book)
book.in_library = 'APP_ID'
# app_id already matches a db_id. No need to set it.
continue
# Sonys know their db_id independent of the application_id
# in the metadata cache. Check that as well.
if getattr(book, 'db_id', None) in d['db_ids']:
update_book(book.db_id, book)
book.in_library = 'DB_ID'
book.application_id = book.db_id
continue
# We now know that the application_id is not right. Set it
# to None to prevent book_on_device from accidentally
# matching on it. It will be set to a correct value below if
# the book is matched with one in the library
book.application_id = None
if book.authors:
# Compare against both author and author sort, because
# either can appear as the author
book_authors = clean_string(authors_to_string(book.authors))
if book_authors in d['authors']:
id_ = d['authors'][book_authors]
update_book(id_, book) update_book(id_, book)
book.in_library = 'AUTHOR' book.in_library = 'UUID'
book.application_id = id_ # ensure that the correct application_id is set
elif book_authors in d['author_sort']: book.application_id = id_
id_ = d['author_sort'][book_authors] continue
# No UUID exact match. Try metadata matching.
book_title = clean_string(book.title)
d = self.db_book_title_cache.get(book_title, None)
if d is not None:
# At this point we know that the title matches. The book
# will match if any of the db_id, author, or author_sort
# also match.
if getattr(book, 'application_id', None) in d['db_ids']:
id_ = getattr(book, 'application_id', None)
update_book(id_, book) update_book(id_, book)
book.in_library = 'AUTH_SORT' book.in_library = 'APP_ID'
book.application_id = id_ # app_id already matches a db_id. No need to set it.
else: continue
# Book definitely not matched. Clear its application ID # Sonys know their db_id independent of the application_id
book.application_id = None # in the metadata cache. Check that as well.
# Set author_sort if it isn't already if getattr(book, 'db_id', None) in d['db_ids']:
asort = getattr(book, 'author_sort', None) update_book(book.db_id, book)
if not asort and book.authors: book.in_library = 'DB_ID'
book.author_sort = self.library_view.model().db.\ book.application_id = book.db_id
author_sort_from_authors(book.authors) continue
# We now know that the application_id is not right. Set it
# to None to prevent book_on_device from accidentally
# matching on it. It will be set to a correct value below if
# the book is matched with one in the library
book.application_id = None
if book.authors:
# Compare against both author and author sort, because
# either can appear as the author
book_authors = clean_string(authors_to_string(book.authors))
if book_authors in d['authors']:
id_ = d['authors'][book_authors]
update_book(id_, book)
book.in_library = 'AUTHOR'
book.application_id = id_
elif book_authors in d['author_sort']:
id_ = d['author_sort'][book_authors]
update_book(id_, book)
book.in_library = 'AUTH_SORT'
book.application_id = id_
else:
# Book definitely not matched. Clear its application ID
book.application_id = None
# Set author_sort if it isn't already
asort = getattr(book, 'author_sort', None)
if not asort and book.authors:
book.author_sort = self.library_view.model().db.\
author_sort_from_authors(book.authors)
if update_metadata: if update_metadata:
if self.device_manager.is_device_connected: if self.device_manager.is_device_connected:
plugboards = self.library_view.model().db.prefs.get('plugboards', {}) plugboards = self.library_view.model().db.prefs.get('plugboards', {})
self.device_manager.sync_booklists( self.device_manager.sync_booklists(
FunctionDispatcher(self.metadata_synced), booklists, FunctionDispatcher(self.metadata_synced), booklists,
plugboards, add_as_step_to_job) plugboards, add_as_step_to_job)
except:
traceback.print_exc()
raise
finally:
QApplication.restoreOverrideCursor()
QApplication.restoreOverrideCursor()
if DEBUG: if DEBUG:
prints('DeviceJob: set_books_in_library finished: time=', time.time() - start_time) prints('DeviceJob: set_books_in_library finished: time=',
time.time() - start_time)
# The status line is reset when the job finishes # The status line is reset when the job finishes
return update_metadata return update_metadata
# }}} # }}}