mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge branch 'master' of https://github.com/davidfor/calibre
Kobo driver: Add support for new firmware Kobo driver: Add an option to not maintain bookmarks/read status/etc. when resending a book already on the device. Fixes #1767589 [New Kobo Glo driver not supported](https://bugs.launchpad.net/calibre/+bug/1767589)
This commit is contained in:
commit
684bbe6dab
@ -52,6 +52,13 @@ def qhash(inputstr):
|
|||||||
return h
|
return h
|
||||||
|
|
||||||
|
|
||||||
|
def any_in(haystack, *needles):
|
||||||
|
for n in needles:
|
||||||
|
if n in haystack:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class DummyCSSPreProcessor(object):
|
class DummyCSSPreProcessor(object):
|
||||||
|
|
||||||
def __call__(self, data, add_namespace=False):
|
def __call__(self, data, add_namespace=False):
|
||||||
@ -69,7 +76,7 @@ class KOBO(USBMS):
|
|||||||
|
|
||||||
dbversion = 0
|
dbversion = 0
|
||||||
fwversion = (0,0,0)
|
fwversion = (0,0,0)
|
||||||
supported_dbversion = 129
|
supported_dbversion = 146
|
||||||
has_kepubs = False
|
has_kepubs = False
|
||||||
|
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
@ -98,33 +105,33 @@ class KOBO(USBMS):
|
|||||||
VIRTUAL_BOOK_EXTENSIONS = frozenset(['kobo', ''])
|
VIRTUAL_BOOK_EXTENSIONS = frozenset(['kobo', ''])
|
||||||
|
|
||||||
EXTRA_CUSTOMIZATION_MESSAGE = [
|
EXTRA_CUSTOMIZATION_MESSAGE = [
|
||||||
_('The Kobo supports several collections including ')+ 'Read, Closed, Im_Reading. ' +
|
_('The Kobo supports several collections including ')+ 'Read, Closed, Im_Reading. ' + _(
|
||||||
_('Create tags for automatic management'),
|
'Create tags for automatic management'),
|
||||||
_('Upload covers for books (newer readers)') +
|
_('Upload covers for books (newer readers)') + ':::'+_(
|
||||||
':::'+_('Normally, the Kobo readers get the cover image from the'
|
'Normally, the Kobo readers get the cover image from the'
|
||||||
' e-book file itself. With this option, calibre will send a '
|
' e-book file itself. With this option, calibre will send a '
|
||||||
'separate cover image to the reader, useful if you '
|
'separate cover image to the reader, useful if you '
|
||||||
'have modified the cover.'),
|
'have modified the cover.'),
|
||||||
_('Upload black and white covers'),
|
_('Upload black and white covers'),
|
||||||
_('Show expired books') +
|
_('Show expired books') + ':::'+_(
|
||||||
':::'+_('A bug in an earlier version left non kepubs book records'
|
'A bug in an earlier version left non kepubs book records'
|
||||||
' in the database. With this option calibre will show the '
|
' in the database. With this option calibre will show the '
|
||||||
'expired records and allow you to delete them with '
|
'expired records and allow you to delete them with '
|
||||||
'the new delete logic.'),
|
'the new delete logic.'),
|
||||||
_('Show Previews') +
|
_('Show Previews') + ':::'+_(
|
||||||
':::'+_('Kobo previews are included on the Touch and some other versions'
|
'Kobo previews are included on the Touch and some other versions'
|
||||||
' by default they are no longer displayed as there is no good reason to '
|
' by default they are no longer displayed as there is no good reason to '
|
||||||
'see them. Enable if you wish to see/delete them.'),
|
'see them. Enable if you wish to see/delete them.'),
|
||||||
_('Show Recommendations') +
|
_('Show Recommendations') + ':::'+_(
|
||||||
':::'+_('Kobo now shows recommendations on the device. In some cases these have '
|
'Kobo now shows recommendations on the device. In some cases these have '
|
||||||
'files but in other cases they are just pointers to the web site to buy. '
|
'files but in other cases they are just pointers to the web site to buy. '
|
||||||
'Enable if you wish to see/delete them.'),
|
'Enable if you wish to see/delete them.'),
|
||||||
_('Attempt to support newer firmware') +
|
_('Attempt to support newer firmware') + ':::'+_(
|
||||||
':::'+_('Kobo routinely updates the firmware and the '
|
'Kobo routinely updates the firmware and the '
|
||||||
'database version. With this option calibre will attempt '
|
'database version. With this option calibre will attempt '
|
||||||
'to perform full read-write functionality - Here be Dragons!! '
|
'to perform full read-write functionality - Here be Dragons!! '
|
||||||
'Enable only if you are comfortable with restoring your kobo '
|
'Enable only if you are comfortable with restoring your kobo '
|
||||||
'to factory defaults and testing software'),
|
'to factory defaults and testing software'),
|
||||||
]
|
]
|
||||||
|
|
||||||
EXTRA_CUSTOMIZATION_DEFAULT = [
|
EXTRA_CUSTOMIZATION_DEFAULT = [
|
||||||
@ -353,8 +360,7 @@ class KOBO(USBMS):
|
|||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
err = str(e)
|
err = str(e)
|
||||||
if not ('___ExpirationStatus' in err or 'FavouritesIndex' in err or
|
if not (any_in(err, '___ExpirationStatus', 'FavouritesIndex', 'Accessibility', 'IsDownloaded')):
|
||||||
'Accessibility' in err or 'IsDownloaded' in err):
|
|
||||||
raise
|
raise
|
||||||
query= ('select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, '
|
query= ('select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, '
|
||||||
'ImageID, ReadStatus, "-1" as ___ExpirationStatus, "-1" as '
|
'ImageID, ReadStatus, "-1" as ___ExpirationStatus, "-1" as '
|
||||||
@ -1316,7 +1322,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
' Based on the existing Kobo driver by %s.') % KOBO.author
|
' Based on the existing Kobo driver by %s.') % KOBO.author
|
||||||
# icon = I('devices/kobotouch.jpg')
|
# icon = I('devices/kobotouch.jpg')
|
||||||
|
|
||||||
supported_dbversion = 143
|
supported_dbversion = 146
|
||||||
min_supported_dbversion = 53
|
min_supported_dbversion = 53
|
||||||
min_dbversion_series = 65
|
min_dbversion_series = 65
|
||||||
min_dbversion_externalid = 65
|
min_dbversion_externalid = 65
|
||||||
@ -1328,7 +1334,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
# Starting with firmware version 3.19.x, the last number appears to be is a
|
# Starting with firmware version 3.19.x, the last number appears to be is a
|
||||||
# build number. A number will be recorded here but it can be safely ignored
|
# build number. A number will be recorded here but it can be safely ignored
|
||||||
# when testing the firmware version.
|
# when testing the firmware version.
|
||||||
max_supported_fwversion = (4, 7, 10413)
|
max_supported_fwversion = (4, 8, 10956)
|
||||||
# The following document firwmare versions where new function or devices were added.
|
# The following document firwmare versions where new function or devices were added.
|
||||||
# Not all are used, but this feels a good place to record it.
|
# Not all are used, but this feels a good place to record it.
|
||||||
min_fwversion_shelves = (2, 0, 0)
|
min_fwversion_shelves = (2, 0, 0)
|
||||||
@ -1337,8 +1343,9 @@ class KOBOTOUCH(KOBO):
|
|||||||
min_aurah2o_fwversion = (3, 7, 0)
|
min_aurah2o_fwversion = (3, 7, 0)
|
||||||
min_reviews_fwversion = (3, 12, 0)
|
min_reviews_fwversion = (3, 12, 0)
|
||||||
min_glohd_fwversion = (3, 14, 0)
|
min_glohd_fwversion = (3, 14, 0)
|
||||||
min_auraone_fwversion = (3, 20, 7280)
|
min_auraone_fwversion = (3, 20, 7280)
|
||||||
min_fwversion_overdrive = (4, 0, 7523)
|
# min_clarahd_fwversion = (4, 8, 10956) # It is coming, this is probably the firmware, but I don't have any ids for it.
|
||||||
|
min_fwversion_overdrive = (4, 0, 7523)
|
||||||
|
|
||||||
has_kepubs = True
|
has_kepubs = True
|
||||||
|
|
||||||
@ -1839,13 +1846,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
err = str(e)
|
err = str(e)
|
||||||
if not ('___ExpirationStatus' in err or
|
if not (any_in(err, '___ExpirationStatus', 'FavouritesIndex', 'Accessibility', 'IsDownloaded', 'Series', 'ExternalId')):
|
||||||
'FavouritesIndex' in err or
|
|
||||||
'Accessibility' in err or
|
|
||||||
'IsDownloaded' in err or
|
|
||||||
'Series' in err or
|
|
||||||
'ExternalId' in err
|
|
||||||
):
|
|
||||||
raise
|
raise
|
||||||
query= ('SELECT Title, Attribution, DateCreated, ContentID, MimeType, ContentType, '
|
query= ('SELECT Title, Attribution, DateCreated, ContentID, MimeType, ContentType, '
|
||||||
'ImageID, ReadStatus, -1 AS ___ExpirationStatus, "-1" AS '
|
'ImageID, ReadStatus, -1 AS ___ExpirationStatus, "-1" AS '
|
||||||
@ -2039,7 +2040,8 @@ class KOBOTOUCH(KOBO):
|
|||||||
# debug_print('KoboTouch:upload_books: Delete record left if deleted on Touch')
|
# debug_print('KoboTouch:upload_books: Delete record left if deleted on Touch')
|
||||||
cursor.execute(cleanup_query, cleanup_values)
|
cursor.execute(cleanup_query, cleanup_values)
|
||||||
|
|
||||||
self.set_filesize_in_device_database(connection, contentID, fname)
|
if self.override_kobo_replace_existing:
|
||||||
|
self.set_filesize_in_device_database(connection, contentID, fname)
|
||||||
|
|
||||||
if not self.upload_covers:
|
if not self.upload_covers:
|
||||||
imageID = self.imageid_from_contentid(contentID)
|
imageID = self.imageid_from_contentid(contentID)
|
||||||
@ -2963,6 +2965,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
c.add_opt('update_device_metadata', default=True)
|
c.add_opt('update_device_metadata', default=True)
|
||||||
|
|
||||||
c.add_opt('modify_css', default=False)
|
c.add_opt('modify_css', default=False)
|
||||||
|
c.add_opt('override_kobo_replace_existing', default=True) # Overriding the replace behaviour is how the driver has always worked.
|
||||||
|
|
||||||
c.add_opt('support_newer_firmware', default=False)
|
c.add_opt('support_newer_firmware', default=False)
|
||||||
c.add_opt('debugging_title', default='')
|
c.add_opt('debugging_title', default='')
|
||||||
@ -3124,6 +3127,10 @@ class KOBOTOUCH(KOBO):
|
|||||||
def modifying_css(self):
|
def modifying_css(self):
|
||||||
return self.get_pref('modify_css')
|
return self.get_pref('modify_css')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def override_kobo_replace_existing(self):
|
||||||
|
return self.get_pref('override_kobo_replace_existing')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def update_device_metadata(self):
|
def update_device_metadata(self):
|
||||||
return self.get_pref('update_device_metadata')
|
return self.get_pref('update_device_metadata')
|
||||||
|
@ -114,6 +114,7 @@ class KOBOTOUCHConfig(TabbedDeviceConfig):
|
|||||||
|
|
||||||
p['update_series'] = self.update_series
|
p['update_series'] = self.update_series
|
||||||
p['modify_css'] = self.modify_css
|
p['modify_css'] = self.modify_css
|
||||||
|
p['override_kobo_replace_existing'] = self.override_kobo_replace_existing
|
||||||
|
|
||||||
p['support_newer_firmware'] = self.support_newer_firmware
|
p['support_newer_firmware'] = self.support_newer_firmware
|
||||||
p['debugging_title'] = self.debugging_title
|
p['debugging_title'] = self.debugging_title
|
||||||
@ -185,14 +186,29 @@ class BookUploadsGroupBox(DeviceOptionsGroupBox):
|
|||||||
'these are removed for all styles in the original stylesheet.').format(device.KOBO_EXTRA_CSSFILE),
|
'these are removed for all styles in the original stylesheet.').format(device.KOBO_EXTRA_CSSFILE),
|
||||||
device.get_pref('modify_css')
|
device.get_pref('modify_css')
|
||||||
)
|
)
|
||||||
|
self.override_kobo_replace_existing_checkbox = create_checkbox(
|
||||||
|
_("Do not treat replacements as new books"),
|
||||||
|
_('When a new book is side-loaded, the Kobo firmware imports details of the book into the internal database. '
|
||||||
|
'Even if the book is a replacement for an existing book, the Kobo will remove the book from the database and then treat it as a new book. '
|
||||||
|
'This means that the reading status, bookmarks and collections for the book will be lost. '
|
||||||
|
'This option overrides firmware behavior and attempts to prevent a book that has been resent from being treated as a new book. '
|
||||||
|
'If you prefer to have replacements treated as new books, turn this option off.'
|
||||||
|
),
|
||||||
|
device.get_pref('override_kobo_replace_existing')
|
||||||
|
)
|
||||||
|
|
||||||
self.options_layout.addWidget(self.modify_css_checkbox, 0, 0, 1, 2)
|
self.options_layout.addWidget(self.modify_css_checkbox, 0, 0, 1, 2)
|
||||||
self.options_layout.setRowStretch(1, 1)
|
self.options_layout.addWidget(self.override_kobo_replace_existing_checkbox, 1, 0, 1, 2)
|
||||||
|
self.options_layout.setRowStretch(2, 1)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def modify_css(self):
|
def modify_css(self):
|
||||||
return self.modify_css_checkbox.isChecked()
|
return self.modify_css_checkbox.isChecked()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def override_kobo_replace_existing(self):
|
||||||
|
return self.override_kobo_replace_existing_checkbox.isChecked()
|
||||||
|
|
||||||
|
|
||||||
class CollectionsGroupBox(DeviceOptionsGroupBox):
|
class CollectionsGroupBox(DeviceOptionsGroupBox):
|
||||||
|
|
||||||
@ -211,7 +227,7 @@ class CollectionsGroupBox(DeviceOptionsGroupBox):
|
|||||||
self.collections_columns_label = QLabel(_('Collections columns:'))
|
self.collections_columns_label = QLabel(_('Collections columns:'))
|
||||||
self.collections_columns_edit = QLineEdit(self)
|
self.collections_columns_edit = QLineEdit(self)
|
||||||
self.collections_columns_edit.setToolTip(_('The Kobo from firmware V2.0.0 supports bookshelves.'
|
self.collections_columns_edit.setToolTip(_('The Kobo from firmware V2.0.0 supports bookshelves.'
|
||||||
' These are created on the Kobo. ' +
|
' These are created on the Kobo. '
|
||||||
'Specify a tags type column for automatic management.'))
|
'Specify a tags type column for automatic management.'))
|
||||||
self.collections_columns_edit.setText(device.get_pref('collections_columns'))
|
self.collections_columns_edit.setText(device.get_pref('collections_columns'))
|
||||||
|
|
||||||
@ -228,8 +244,8 @@ class CollectionsGroupBox(DeviceOptionsGroupBox):
|
|||||||
|
|
||||||
self.ignore_collections_names_label = QLabel(_('Ignore collections:'))
|
self.ignore_collections_names_label = QLabel(_('Ignore collections:'))
|
||||||
self.ignore_collections_names_edit = QLineEdit(self)
|
self.ignore_collections_names_edit = QLineEdit(self)
|
||||||
self.ignore_collections_names_edit.setToolTip(_('List the names of collections to be ignored by ' +
|
self.ignore_collections_names_edit.setToolTip(_('List the names of collections to be ignored by '
|
||||||
'the collection management. The collections listed ' +
|
'the collection management. The collections listed '
|
||||||
'will not be changed. Names are separated by commas.'))
|
'will not be changed. Names are separated by commas.'))
|
||||||
self.ignore_collections_names_edit.setText(device.get_pref('ignore_collections_names'))
|
self.ignore_collections_names_edit.setText(device.get_pref('ignore_collections_names'))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user