newdb: Speed up S&R in the bulk metadata edit dialog

This commit is contained in:
Kovid Goyal 2013-08-25 17:30:34 +05:30
parent 1ea50f3d40
commit 138de9b699
2 changed files with 21 additions and 41 deletions

View File

@ -352,11 +352,12 @@ class EditMetadataAction(InterfaceAction):
# Prevent the TagView from updating due to signals from the database
self.gui.tags_view.blockSignals(True)
changed = False
refresh_books = set(book_ids)
try:
current_tab = 0
while True:
dialog = MetadataBulkDialog(self.gui, rows,
self.gui.library_view.model(), current_tab)
self.gui.library_view.model(), current_tab, refresh_books)
if dialog.changed:
changed = True
if not dialog.do_again:
@ -365,12 +366,13 @@ class EditMetadataAction(InterfaceAction):
finally:
self.gui.tags_view.blockSignals(False)
if changed:
refresh_books |= dialog.refresh_books
m = self.gui.library_view.model()
if gprefs['refresh_book_list_on_bulk_edit']:
m.refresh(reset=False)
m.research()
else:
m.refresh_ids(book_ids)
m.refresh_ids(refresh_books)
self.gui.tags_view.recount()
if self.gui.cover_flow:
self.gui.cover_flow.dataChanged()

View File

@ -3,8 +3,8 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
'''Dialog to edit metadata in bulk'''
import re, os, inspect
from collections import namedtuple
import re, os
from collections import namedtuple, defaultdict
from threading import Thread
from PyQt4.Qt import Qt, QDialog, QGridLayout, QVBoxLayout, QFont, QLabel, \
@ -62,7 +62,7 @@ class MyBlockingBusy(QDialog): # {{{
all_done = pyqtSignal()
def __init__(self, args, ids, db, cc_widgets, s_r_func, do_sr, parent=None, window_title=_('Working')):
def __init__(self, args, ids, db, refresh_books, cc_widgets, s_r_func, do_sr, sr_calls, parent=None, window_title=_('Working')):
QDialog.__init__(self, parent)
self._layout = l = QVBoxLayout()
@ -86,6 +86,8 @@ class MyBlockingBusy(QDialog): # {{{
self.db, self.cc_widgets = db, cc_widgets
self.s_r_func = FunctionDispatcher(s_r_func)
self.do_sr = do_sr
self.sr_calls = sr_calls
self.refresh_books = refresh_books
def accept(self):
pass
@ -276,6 +278,10 @@ class MyBlockingBusy(QDialog): # {{{
if self.do_sr:
for book_id in self.ids:
self.s_r_func(book_id)
if self.sr_calls:
for field, book_id_val_map in self.sr_calls.iteritems():
self.refresh_books.update(self.db.new_api.set_field(field, book_id_val_map))
# }}}
class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
@ -296,7 +302,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
_('Append to field'),
]
def __init__(self, window, rows, model, tab):
def __init__(self, window, rows, model, tab, refresh_books):
ResizableDialog.__init__(self, window)
Ui_MetadataBulkDialog.__init__(self)
self.model = model
@ -309,6 +315,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
len(rows))
self.write_series = False
self.changed = False
self.refresh_books = refresh_books
all_tags = self.db.all_tags()
self.tags.update_items_cache(all_tags)
@ -790,7 +797,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
self.s_r_set_colors()
break
def do_search_replace(self, id):
def do_search_replace(self, book_id):
source = self.s_r_sf_itemdata(None)
if not source or not self.s_r_obj:
return
@ -798,7 +805,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
if not dest:
dest = source
dfm = self.db.field_metadata[dest]
mi = self.db.get_metadata(id, index_is_id=True)
mi = self.db.new_api.get_proxy_metadata(book_id)
val = self.s_r_do_regexp(mi)
val = self.s_r_do_destination(mi, val)
if dfm['is_multiple']:
@ -823,37 +830,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
if dest == 'title' and len(val) == 0:
val = _('Unknown')
if dfm['is_custom']:
extra = self.db.get_custom_extra(id, label=dfm['label'], index_is_id=True)
books_to_refresh = self.db.set_custom(id, val, label=dfm['label'],
extra=extra, commit=False,
allow_case_change=True)
elif dest.startswith('#') and dest.endswith('_index'):
label = self.db.field_metadata[dest[:-6]]['label']
series = self.db.get_custom(id, label=label, index_is_id=True)
books_to_refresh = self.db.set_custom(id, series, label=label,
extra=val, commit=False,
allow_case_change=True)
else:
if dest == 'comments':
setter = self.db.set_comment
elif dest == 'sort':
setter = self.db.set_title_sort
else:
setter = getattr(self.db, 'set_'+dest)
args = inspect.getargspec(setter)
if args and 'allow_case_change' in args.args:
books_to_refresh = setter(id, val, notify=False, commit=False,
allow_case_change=True)
else:
setter(id, val, notify=False, commit=False)
books_to_refresh = set([])
if books_to_refresh:
# Must commit here because we are telling the gui that the data is
# permanent. Make sure it really is.
self.db.commit()
self.model.refresh_ids(list(books_to_refresh))
self.set_field_calls[dest][book_id] = val
# }}}
def create_custom_column_editors(self):
@ -993,9 +970,10 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
source = self.s_r_sf_itemdata(None)
do_sr = source and self.s_r_obj
bb = MyBlockingBusy(args, self.ids, self.db,
self.set_field_calls = defaultdict(dict)
bb = MyBlockingBusy(args, self.ids, self.db, self.refresh_books,
getattr(self, 'custom_column_widgets', []),
self.do_search_replace, do_sr, parent=self)
self.do_search_replace, do_sr, self.set_field_calls, parent=self)
# The metadata backup thread causes database commits
# which can slow down bulk editing of large numbers of books