This commit is contained in:
Kovid Goyal 2021-09-14 08:35:19 +05:30
commit 38de7930c7
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 48 additions and 32 deletions

View File

@ -1230,8 +1230,8 @@ class Cache(object):
else:
v = sid = None
if sid is None and name.startswith('#'):
extra = self._fast_field_for(sfield, k)
sid = extra or 1.0 # The value to be set the db link table
sid = self._fast_field_for(sfield, k)
sid = 1.0 if sid is None else sid # The value to be set the db link table
bimap[k] = v
if sid is not None:
simap[k] = sid
@ -1244,11 +1244,11 @@ class Cache(object):
sf = self.fields[f.name+'_index']
dirtied |= sf.writer.set_books(simap, self.backend, allow_case_change=False)
if dirtied and update_path and do_path_update:
self._update_path(dirtied, mark_as_dirtied=False)
self._mark_as_dirty(dirtied)
self.event_dispatcher(EventType.metadata_changed, name, dirtied)
if dirtied:
if update_path and do_path_update:
self._update_path(dirtied, mark_as_dirtied=False)
self._mark_as_dirty(dirtied)
self.event_dispatcher(EventType.metadata_changed, name, dirtied)
return dirtied
@write_api

View File

@ -192,6 +192,12 @@ def get_adapter(name, metadata):
def one_one_in_books(book_id_val_map, db, field, *args):
'Set a one-one field in the books table'
# Ignore those items whose value is the same as the current value
# We can't do this for the cover because the file might change without
# the presence-of-cover flag changing
if field.name != 'cover':
book_id_val_map = {k:v for k, v in iteritems(book_id_val_map)
if v != field.table.book_col_map.get(k, None)}
if book_id_val_map:
sequence = ((sqlite_datetime(v), k) for k, v in iteritems(book_id_val_map))
db.executemany(
@ -207,14 +213,17 @@ def set_uuid(book_id_val_map, db, field, *args):
def set_title(book_id_val_map, db, field, *args):
ans = one_one_in_books(book_id_val_map, db, field, *args)
# Set the title sort field
# Set the title sort field if the title changed
field.title_sort_field.writer.set_books(
{k:title_sort(v) for k, v in iteritems(book_id_val_map)}, db)
{k:title_sort(v) for k, v in iteritems(book_id_val_map) if k in ans}, db)
return ans
def one_one_in_other(book_id_val_map, db, field, *args):
'Set a one-one field in the non-books table, like comments'
# Ignore those items whose value is the same as the current value
book_id_val_map = {k:v for k, v in iteritems(book_id_val_map)
if v != field.table.book_col_map.get(k, None)}
deleted = tuple((k,) for k, v in iteritems(book_id_val_map) if v is None)
if deleted:
db.executemany('DELETE FROM %s WHERE book=?'%field.metadata['table'],
@ -234,12 +243,13 @@ def custom_series_index(book_id_val_map, db, field, *args):
series_field = field.series_field
sequence = []
for book_id, sidx in book_id_val_map.items():
ids = series_field.ids_for_book(book_id)
if sidx is None:
sidx = 1.0
ids = series_field.ids_for_book(book_id)
if ids:
sequence.append((sidx, book_id, ids[0]))
field.table.book_col_map[book_id] = sidx
if field.table.book_col_map.get(book_id, None) != sidx:
sequence.append((sidx, book_id, ids[0]))
field.table.book_col_map[book_id] = sidx
else:
# the series has been deleted from the book, which means no row for
# it exists in the series table. The series_index value should be
@ -427,7 +437,7 @@ def many_many(book_id_val_map, db, field, allow_case_change, *args):
# Ignore those items whose value is the same as the current value
book_id_item_id_map = {k:v for k, v in iteritems(book_id_item_id_map)
if v != table.book_col_map.get(k, None)}
if v != table.book_col_map.get(k, tuple())}
dirtied |= set(book_id_item_id_map)
# Update the book->col and col->book maps
@ -484,6 +494,10 @@ def many_many(book_id_val_map, db, field, allow_case_change, *args):
def identifiers(book_id_val_map, db, field, *args): # {{{
# Ignore those items whose value is the same as the current value
book_id_val_map = {k:v for k, v in iteritems(book_id_val_map)
if v != field.table.book_col_map.get(k, None)}
table = field.table
updates = set()
for book_id, identifiers in iteritems(book_id_val_map):

View File

@ -1266,14 +1266,12 @@ class BuiltinAnnotationCount(BuiltinFormatterFunction):
'This function works only in the GUI.')
def evaluate(self, formatter, kwargs, mi, locals):
if hasattr(mi, '_proxy_metadata'):
try:
from calibre.gui2.ui import get_gui
c = get_gui().current_db.new_api.annotation_count_for_book(mi.id)
return '' if c == 0 else unicode_type(c)
except:
return _('Failed to fetch annotation count')
return ''
try:
from calibre.gui2.ui import get_gui
c = get_gui().current_db.new_api.annotation_count_for_book(mi.id)
return '' if c == 0 else unicode_type(c)
except:
pass
return _('This function can be used only in the GUI')
@ -1287,14 +1285,12 @@ class BuiltinIsMarked(BuiltinFormatterFunction):
"marks. Returns '' if the book is not marked.")
def evaluate(self, formatter, kwargs, mi, locals):
if hasattr(mi, '_proxy_metadata'):
try:
from calibre.gui2.ui import get_gui
c = get_gui().current_db.data.get_marked(mi.id)
return c if c else ''
except:
return _('Failed to get marked status')
return ''
try:
from calibre.gui2.ui import get_gui
c = get_gui().current_db.data.get_marked(mi.id)
return c if c else ''
except:
pass
return _('This function can be used only in the GUI')
@ -1762,10 +1758,12 @@ class BuiltinVirtualLibraries(BuiltinFormatterFunction):
'column\'s value in your save/send templates')
def evaluate(self, formatter, kwargs, mi, locals_):
if hasattr(mi, '_proxy_metadata'):
try:
from calibre.gui2.ui import get_gui
a = get_gui().current_db.data.get_virtual_libraries_for_books((mi.id,))
return ', '.join(a[mi.id])
except:
pass
return _('This function can be used only in the GUI')
@ -1863,7 +1861,7 @@ class BuiltinConnectedDeviceName(BuiltinFormatterFunction):
"'carda' and 'cardb'. This function works only in the GUI.")
def evaluate(self, formatter, kwargs, mi, locals, storage_location):
if hasattr(mi, '_proxy_metadata'):
try:
# Do the import here so that we don't entangle the GUI when using
# command line functions
from calibre.gui2.ui import get_gui
@ -1882,6 +1880,8 @@ class BuiltinConnectedDeviceName(BuiltinFormatterFunction):
except:
traceback.print_exc()
raise
except:
pass
return _('This function can be used only in the GUI')
@ -1897,7 +1897,7 @@ class BuiltinConnectedDeviceUUID(BuiltinFormatterFunction):
"the GUI.")
def evaluate(self, formatter, kwargs, mi, locals, storage_location):
if hasattr(mi, '_proxy_metadata'):
try:
# Do the import here so that we don't entangle the GUI when using
# command line functions
from calibre.gui2.ui import get_gui
@ -1916,6 +1916,8 @@ class BuiltinConnectedDeviceUUID(BuiltinFormatterFunction):
except:
traceback.print_exc()
raise
except:
pass
return _('This function can be used only in the GUI')