Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/davidfor/calibre
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
kovidgoyal committed Apr 28, 2018
2 parents db93604 + f825161 commit 684bbe6
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 45 deletions.
89 changes: 48 additions & 41 deletions src/calibre/devices/kobo/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ def qhash(inputstr):
return h


def any_in(haystack, *needles):
for n in needles:
if n in haystack:
return True
return False


class DummyCSSPreProcessor(object):

def __call__(self, data, add_namespace=False):
Expand All @@ -69,7 +76,7 @@ class KOBO(USBMS):

dbversion = 0
fwversion = (0,0,0)
supported_dbversion = 129
supported_dbversion = 146
has_kepubs = False

supported_platforms = ['windows', 'osx', 'linux']
Expand Down Expand Up @@ -98,33 +105,33 @@ class KOBO(USBMS):
VIRTUAL_BOOK_EXTENSIONS = frozenset(['kobo', ''])

EXTRA_CUSTOMIZATION_MESSAGE = [
_('The Kobo supports several collections including ')+ 'Read, Closed, Im_Reading. ' +
_('Create tags for automatic management'),
_('Upload covers for books (newer readers)') +
':::'+_('Normally, the Kobo readers get the cover image from the'
' e-book file itself. With this option, calibre will send a '
'separate cover image to the reader, useful if you '
'have modified the cover.'),
_('The Kobo supports several collections including ')+ 'Read, Closed, Im_Reading. ' + _(
'Create tags for automatic management'),
_('Upload covers for books (newer readers)') + ':::'+_(
'Normally, the Kobo readers get the cover image from the'
' e-book file itself. With this option, calibre will send a '
'separate cover image to the reader, useful if you '
'have modified the cover.'),
_('Upload black and white covers'),
_('Show expired books') +
':::'+_('A bug in an earlier version left non kepubs book records'
' in the database. With this option calibre will show the '
'expired records and allow you to delete them with '
'the new delete logic.'),
_('Show Previews') +
':::'+_('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 '
'see them. Enable if you wish to see/delete them.'),
_('Show Recommendations') +
':::'+_('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. '
'Enable if you wish to see/delete them.'),
_('Attempt to support newer firmware') +
':::'+_('Kobo routinely updates the firmware and the '
'database version. With this option calibre will attempt '
'to perform full read-write functionality - Here be Dragons!! '
'Enable only if you are comfortable with restoring your kobo '
'to factory defaults and testing software'),
_('Show expired books') + ':::'+_(
'A bug in an earlier version left non kepubs book records'
' in the database. With this option calibre will show the '
'expired records and allow you to delete them with '
'the new delete logic.'),
_('Show Previews') + ':::'+_(
'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 '
'see them. Enable if you wish to see/delete them.'),
_('Show Recommendations') + ':::'+_(
'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. '
'Enable if you wish to see/delete them.'),
_('Attempt to support newer firmware') + ':::'+_(
'Kobo routinely updates the firmware and the '
'database version. With this option calibre will attempt '
'to perform full read-write functionality - Here be Dragons!! '
'Enable only if you are comfortable with restoring your kobo '
'to factory defaults and testing software'),
]

EXTRA_CUSTOMIZATION_DEFAULT = [
Expand Down Expand Up @@ -353,8 +360,7 @@ def update_booklist(prefix, path, title, authors, mime, date, ContentType, Image
cursor.execute(query)
except Exception as e:
err = str(e)
if not ('___ExpirationStatus' in err or 'FavouritesIndex' in err or
'Accessibility' in err or 'IsDownloaded' in err):
if not (any_in(err, '___ExpirationStatus', 'FavouritesIndex', 'Accessibility', 'IsDownloaded')):
raise
query= ('select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, '
'ImageID, ReadStatus, "-1" as ___ExpirationStatus, "-1" as '
Expand Down Expand Up @@ -1316,7 +1322,7 @@ class KOBOTOUCH(KOBO):
' Based on the existing Kobo driver by %s.') % KOBO.author
# icon = I('devices/kobotouch.jpg')

supported_dbversion = 143
supported_dbversion = 146
min_supported_dbversion = 53
min_dbversion_series = 65
min_dbversion_externalid = 65
Expand All @@ -1328,7 +1334,7 @@ class KOBOTOUCH(KOBO):
# 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
# 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.
# Not all are used, but this feels a good place to record it.
min_fwversion_shelves = (2, 0, 0)
Expand All @@ -1337,8 +1343,9 @@ class KOBOTOUCH(KOBO):
min_aurah2o_fwversion = (3, 7, 0)
min_reviews_fwversion = (3, 12, 0)
min_glohd_fwversion = (3, 14, 0)
min_auraone_fwversion = (3, 20, 7280)
min_fwversion_overdrive = (4, 0, 7523)
min_auraone_fwversion = (3, 20, 7280)
# 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

Expand Down Expand Up @@ -1839,13 +1846,7 @@ def get_bookshelvesforbook(connection, ContentID):
cursor.execute(query)
except Exception as e:
err = str(e)
if not ('___ExpirationStatus' in err or
'FavouritesIndex' in err or
'Accessibility' in err or
'IsDownloaded' in err or
'Series' in err or
'ExternalId' in err
):
if not (any_in(err, '___ExpirationStatus', 'FavouritesIndex', 'Accessibility', 'IsDownloaded', 'Series', 'ExternalId')):
raise
query= ('SELECT Title, Attribution, DateCreated, ContentID, MimeType, ContentType, '
'ImageID, ReadStatus, -1 AS ___ExpirationStatus, "-1" AS '
Expand Down Expand Up @@ -2039,7 +2040,8 @@ def upload_books(self, files, names, on_card=None, end_session=True,
# debug_print('KoboTouch:upload_books: Delete record left if deleted on Touch')
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:
imageID = self.imageid_from_contentid(contentID)
Expand Down Expand Up @@ -2963,6 +2965,7 @@ def _config(cls):
c.add_opt('update_device_metadata', default=True)

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('debugging_title', default='')
Expand Down Expand Up @@ -3124,6 +3127,10 @@ def modifying_epub(self):
def modifying_css(self):
return self.get_pref('modify_css')

@property
def override_kobo_replace_existing(self):
return self.get_pref('override_kobo_replace_existing')

@property
def update_device_metadata(self):
return self.get_pref('update_device_metadata')
Expand Down
24 changes: 20 additions & 4 deletions src/calibre/devices/kobo/kobotouch_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ def commit(self):

p['update_series'] = self.update_series
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['debugging_title'] = self.debugging_title
Expand Down Expand Up @@ -185,14 +186,29 @@ def __init__(self, parent, device):
'these are removed for all styles in the original stylesheet.').format(device.KOBO_EXTRA_CSSFILE),
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.setRowStretch(1, 1)
self.options_layout.addWidget(self.override_kobo_replace_existing_checkbox, 1, 0, 1, 2)
self.options_layout.setRowStretch(2, 1)

@property
def modify_css(self):
return self.modify_css_checkbox.isChecked()

@property
def override_kobo_replace_existing(self):
return self.override_kobo_replace_existing_checkbox.isChecked()


class CollectionsGroupBox(DeviceOptionsGroupBox):

Expand All @@ -211,7 +227,7 @@ def __init__(self, parent, device):
self.collections_columns_label = QLabel(_('Collections columns:'))
self.collections_columns_edit = QLineEdit(self)
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.'))
self.collections_columns_edit.setText(device.get_pref('collections_columns'))

Expand All @@ -228,8 +244,8 @@ def __init__(self, parent, device):

self.ignore_collections_names_label = QLabel(_('Ignore collections:'))
self.ignore_collections_names_edit = QLineEdit(self)
self.ignore_collections_names_edit.setToolTip(_('List the names of collections to be ignored by ' +
'the collection management. The collections listed ' +
self.ignore_collections_names_edit.setToolTip(_('List the names of collections to be ignored by '
'the collection management. The collections listed '
'will not be changed. Names are separated by commas.'))
self.ignore_collections_names_edit.setText(device.get_pref('ignore_collections_names'))

Expand Down

0 comments on commit 684bbe6

Please sign in to comment.