mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
2d406eb2a1
@ -355,8 +355,6 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
self.debug_start_time = time.time()
|
||||
self.debug_time = time.time()
|
||||
|
||||
# This must be protected by a lock because it is called from three threads
|
||||
@synchronous('sync_lock')
|
||||
def _debug(self, *args):
|
||||
# manual synchronization so we don't lose the calling method name
|
||||
import inspect
|
||||
@ -694,8 +692,8 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
return None
|
||||
|
||||
def _metadata_in_cache(self, uuid, ext_or_lpath, lastmod):
|
||||
from calibre.utils.date import now, parse_date
|
||||
try:
|
||||
from calibre.utils.date import parse_date, now
|
||||
key = self._make_metadata_cache_key(uuid, ext_or_lpath)
|
||||
if isinstance(lastmod, unicode):
|
||||
if lastmod == 'None':
|
||||
@ -795,8 +793,8 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
traceback.print_exc()
|
||||
|
||||
def _write_metadata_cache(self):
|
||||
self._debug()
|
||||
from calibre.utils.date import now
|
||||
self._debug()
|
||||
from calibre.utils.config import to_json
|
||||
cache_file_name = os.path.join(cache_dir(),
|
||||
'wireless_device_' + self.device_uuid +
|
||||
@ -990,7 +988,8 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
'currentLibraryUUID': library_uuid,
|
||||
'pubdateFormat': tweaks['gui_pubdate_display_format'],
|
||||
'timestampFormat': tweaks['gui_timestamp_display_format'],
|
||||
'lastModifiedFormat': tweaks['gui_last_modified_display_format']})
|
||||
'lastModifiedFormat': tweaks['gui_last_modified_display_format'],
|
||||
'calibre_version': numeric_version})
|
||||
if opcode != 'OK':
|
||||
# Something wrong with the return. Close the socket
|
||||
# and continue.
|
||||
@ -1089,7 +1088,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
self.is_read_sync_col = result.get('isReadSyncCol', None)
|
||||
self._debug('Device is_read sync col', self.is_read_sync_col)
|
||||
|
||||
self.is_read_date_sync_col = result.get('isReadDateSyncCol', False)
|
||||
self.is_read_date_sync_col = result.get('isReadDateSyncCol', None)
|
||||
self._debug('Device is_read_date sync col', self.is_read_date_sync_col)
|
||||
|
||||
if password:
|
||||
@ -1209,7 +1208,8 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
{'canStream':True,
|
||||
'canScan':True,
|
||||
'willUseCachedMetadata': self.client_can_use_metadata_cache,
|
||||
'supportsSync': True})
|
||||
'supportsSync': (self.is_read_sync_col or
|
||||
self.is_read_date_sync_col)})
|
||||
bl = CollectionsBookList(None, self.PREFIX, self.settings)
|
||||
if opcode == 'OK':
|
||||
count = result['count']
|
||||
@ -1257,7 +1257,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
book = self.json_codec.raw_to_book(result, SDBook, self.PREFIX)
|
||||
book.set('_is_read_', result.get('_is_read_', None))
|
||||
book.set('_is_read_changed_', result.get('_is_read_changed_', None))
|
||||
book.set('_last_read_date_', r.get('_last_read_date_', None))
|
||||
book.set('_last_read_date_', result.get('_last_read_date_', None))
|
||||
bl.add_book(book, replace_metadata=True)
|
||||
if '_new_book_' in result:
|
||||
book.set('_new_book_', True)
|
||||
@ -1309,7 +1309,8 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
self._call_client('SEND_BOOKLISTS', {'count': count,
|
||||
'collections': coldict,
|
||||
'willStreamMetadata': True,
|
||||
'supportsSync': True},
|
||||
'supportsSync': (self.is_read_sync_col or
|
||||
self.is_read_date_sync_col)},
|
||||
wait_for_response=False)
|
||||
|
||||
if count:
|
||||
@ -1318,7 +1319,9 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
self._set_known_metadata(book)
|
||||
opcode, result = self._call_client(
|
||||
'SEND_BOOK_METADATA',
|
||||
{'index': i, 'count': count, 'data': book, 'supportsSync': True},
|
||||
{'index': i, 'count': count, 'data': book,
|
||||
'supportsSync': (self.is_read_sync_col or
|
||||
self.is_read_date_sync_col)},
|
||||
print_debug_info=False,
|
||||
wait_for_response=False)
|
||||
|
||||
@ -1466,86 +1469,123 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
|
||||
@synchronous('sync_lock')
|
||||
def synchronize_with_db(self, db, id_, book):
|
||||
from calibre.utils.date import parse_date, UNDEFINED_DATE
|
||||
def show_message(message):
|
||||
self._call_client("DISPLAY_MESSAGE",
|
||||
{'messageKind': self.MESSAGE_SHOW_TOAST,
|
||||
'message': message})
|
||||
|
||||
if not (self.is_read_sync_col or self.is_read_date_sync_col):
|
||||
# Not syncing
|
||||
if self.have_bad_sync_columns or not (self.is_read_sync_col or
|
||||
self.is_read_date_sync_col):
|
||||
# Not syncing or sync columns are invalid
|
||||
return None
|
||||
|
||||
# Check the validity of the columns once per connection. We do it
|
||||
# here because we have access to the db to get field_metadata
|
||||
if not self.have_checked_sync_columns:
|
||||
# Check the validity of the columns once per connection. We do it
|
||||
# here because we have access to the db to get field_metadata
|
||||
fm = db.field_metadata.custom_field_metadata()
|
||||
if self.is_read_sync_col:
|
||||
if self.is_read_sync_col not in fm:
|
||||
self._debug('is_read_sync_col not in field_metadata')
|
||||
show_message(_("The read sync column %s is "
|
||||
"not in calibre's library")%self.is_read_sync_col)
|
||||
self.have_bad_sync_columns = True
|
||||
elif fm[self.is_read_sync_col]['datatype'] != 'bool':
|
||||
self._debug('is_read_sync_col not bool type')
|
||||
show_message(_("The read sync column %s is "
|
||||
"not a Yes/No column")%self.is_read_sync_col)
|
||||
self.have_bad_sync_columns = True
|
||||
|
||||
if self.is_read_date_sync_col:
|
||||
if self.is_read_date_sync_col not in fm:
|
||||
self._debug('is_read_date_sync_col not in field_metadata')
|
||||
show_message(_("The read date sync column %s is "
|
||||
"not in calibre's library")%self.is_read_date_sync_col)
|
||||
self.have_bad_sync_columns = True
|
||||
elif fm[self.is_read_date_sync_col]['datatype'] != 'datetime':
|
||||
self._debug('is_read_date_sync_col not date type')
|
||||
show_message(_("The read date sync column %s is "
|
||||
"not a Date column")%self.is_read_date_sync_col)
|
||||
self.have_bad_sync_columns = True
|
||||
|
||||
self.have_checked_sync_columns = True
|
||||
if self.have_bad_sync_columns:
|
||||
return None
|
||||
|
||||
is_changed = book.get('_is_read_changed_', None);
|
||||
is_read = book.get('_is_read_', None)
|
||||
# This returns UNDEFINED_DATE if the value is None
|
||||
is_read_date = parse_date(book.get('_last_read_date_', None));
|
||||
value_to_return = None
|
||||
|
||||
if is_changed == 2 and is_read is None:
|
||||
if is_changed == 2:
|
||||
# This is a special case where the user just set the sync column. In
|
||||
# this case the device value wins if it is not None by falling
|
||||
# through to the normal sync situation below, otherwise the calibre
|
||||
# value wins.
|
||||
calibre_val = db.new_api.field_for(self.is_read_sync_col,
|
||||
id_, default_value=None)
|
||||
if calibre_val is not None:
|
||||
# This will force the metadata for the book to be sent . Note
|
||||
# that because the devices last_read date is one-way sync, this
|
||||
# could leave an empty date in the device.
|
||||
book.set('_force_send_metadata_', True)
|
||||
self._debug('special update book', book.get('title', 'huh?'),
|
||||
'to', calibre_val)
|
||||
return set(id_)
|
||||
# Both values are None. Do nothing
|
||||
return None
|
||||
# value wins. The orig_* values are set to None to force the normal
|
||||
# sync code to actually sync because the values are different
|
||||
orig_is_read_date = UNDEFINED_DATE
|
||||
orig_is_read = None
|
||||
if is_read is None:
|
||||
calibre_val = db.new_api.field_for(self.is_read_sync_col,
|
||||
id_, default_value=None)
|
||||
if calibre_val is not None:
|
||||
# This forces the metadata for the book to be sent to the
|
||||
# device even if the mod dates haven't changed.
|
||||
book.set('_force_send_metadata_', True)
|
||||
self._debug('special update is_read', book.get('title', 'huh?'),
|
||||
'to', calibre_val)
|
||||
value_to_return = set()
|
||||
|
||||
orig_is_read = book.get(self.is_read_sync_col, None)
|
||||
if is_read != orig_is_read:
|
||||
# The value in the device's is_read checkbox is not the same as the
|
||||
# last one that came to the device from calibre during the last
|
||||
# connect, meaning that the user changed it. Write the one from the
|
||||
# checkbox to calibre's db.
|
||||
changed_books = set()
|
||||
is_read_date = book.get('_last_read_date_', None);
|
||||
self._debug('standard update book', book.get('title', 'huh?'), 'to',
|
||||
is_read, is_read_date)
|
||||
if self.is_read_sync_col:
|
||||
try:
|
||||
if is_read_date == UNDEFINED_DATE:
|
||||
calibre_val = db.new_api.field_for(self.is_read_date_sync_col,
|
||||
id_, default_value=None)
|
||||
if calibre_val != UNDEFINED_DATE:
|
||||
book.set('_force_send_metadata_', True)
|
||||
self._debug('special update is_read_date', book.get('title', 'huh?'),
|
||||
'to', calibre_val)
|
||||
value_to_return = set()
|
||||
# Fall through to the normal sync. At this point either the is_read*
|
||||
# values are different from the orig_is_read* which will cause a
|
||||
# sync below, or they are both None which will cause the code below
|
||||
# to do nothing. If either of the calibre data fields were set, the
|
||||
# method will return set(), which will force updated metadata to be
|
||||
# given back to the device, effectively forcing the sync of the
|
||||
# calibre values back to the device.
|
||||
else:
|
||||
orig_is_read = book.get(self.is_read_sync_col, None)
|
||||
orig_is_read_date = book.get(self.is_read_date_sync_col, None)
|
||||
|
||||
changed_books = set()
|
||||
try:
|
||||
if is_read != orig_is_read:
|
||||
# The value in the device's is_read checkbox is not the same as the
|
||||
# last one that came to the device from calibre during the last
|
||||
# connect, meaning that the user changed it. Write the one from the
|
||||
# device to calibre's db.
|
||||
self._debug('standard update book is_read', book.get('title', 'huh?'),
|
||||
'to', is_read)
|
||||
if self.is_read_sync_col:
|
||||
changed_books = db.new_api.set_field(self.is_read_sync_col,
|
||||
{id_: is_read})
|
||||
except:
|
||||
self._debug('setting read sync col tossed exception',
|
||||
self.is_read_sync_col)
|
||||
if self.is_read_date_sync_col:
|
||||
try:
|
||||
except:
|
||||
self._debug('exception syncing is_read col', self.is_read_sync_col)
|
||||
traceback.print_exc()
|
||||
|
||||
try:
|
||||
if is_read_date != orig_is_read_date:
|
||||
self._debug('standard update book is_read_date', book.get('title', 'huh?'),
|
||||
'to', is_read_date)
|
||||
if self.is_read_date_sync_col:
|
||||
changed_books |= db.new_api.set_field(self.is_read_date_sync_col,
|
||||
{id_: is_read_date})
|
||||
except:
|
||||
self._debug('setting read date sync col tossed exception',
|
||||
self.is_read_date_sync_col)
|
||||
{id_: is_read_date})
|
||||
except:
|
||||
self._debug('Exception while syncing is_read_date', self.is_read_date_sync_col)
|
||||
traceback.print_exc()
|
||||
|
||||
if changed_books:
|
||||
# One of the two values was synced, giving a list of changed books.
|
||||
# Return that.
|
||||
return changed_books
|
||||
|
||||
# The user might have changed the value in calibre. If so, that value
|
||||
@ -1553,7 +1593,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
# updated value has already been synced and so will also be sent, the
|
||||
# device should put the calibre value into its checkbox (or whatever it
|
||||
# uses)
|
||||
return None
|
||||
return value_to_return
|
||||
|
||||
@synchronous('sync_lock')
|
||||
def startup(self):
|
||||
@ -1581,6 +1621,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
|
||||
self.is_read_sync_col = None
|
||||
self.is_read_date_sync_col = None
|
||||
self.have_checked_sync_columns = False
|
||||
self.have_bad_sync_columns = False
|
||||
|
||||
message = None
|
||||
compression_quality_ok = True
|
||||
|
Loading…
x
Reference in New Issue
Block a user