mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Kobo driver: Add support for new firmware with the series list on the device
Merge branch 'master' of https://github.com/davidfor/calibre
This commit is contained in:
commit
477d9ef560
@ -70,6 +70,7 @@ class Book(Book_):
|
|||||||
self.can_put_on_shelves = True
|
self.can_put_on_shelves = True
|
||||||
self.kobo_series = None
|
self.kobo_series = None
|
||||||
self.kobo_series_number = None # Kobo stores the series number as string. And it can have a leading "#".
|
self.kobo_series_number = None # Kobo stores the series number as string. And it can have a leading "#".
|
||||||
|
self.kobo_series_id = None
|
||||||
self.kobo_subtitle = None
|
self.kobo_subtitle = None
|
||||||
|
|
||||||
if thumbnail_name is not None:
|
if thumbnail_name is not None:
|
||||||
@ -84,6 +85,10 @@ class Book(Book_):
|
|||||||
# If we don't have a content Id, we don't know what type it is.
|
# If we don't have a content Id, we don't know what type it is.
|
||||||
return self.contentID and self.contentID.startswith("file")
|
return self.contentID and self.contentID.startswith("file")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_kobo_series(self):
|
||||||
|
return self.kobo_series is not None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_purchased_kepub(self):
|
def is_purchased_kepub(self):
|
||||||
return self.contentID and not self.contentID.startswith("file")
|
return self.contentID and not self.contentID.startswith("file")
|
||||||
@ -102,6 +107,8 @@ class Book(Book_):
|
|||||||
fmt('Content ID', self.contentID)
|
fmt('Content ID', self.contentID)
|
||||||
if self.kobo_series:
|
if self.kobo_series:
|
||||||
fmt('Kobo Series', self.kobo_series + ' #%s'%self.kobo_series_number)
|
fmt('Kobo Series', self.kobo_series + ' #%s'%self.kobo_series_number)
|
||||||
|
if self.kobo_series_id:
|
||||||
|
fmt('Kobo Series ID', self.kobo_series_id)
|
||||||
if self.kobo_subtitle:
|
if self.kobo_subtitle:
|
||||||
fmt('Subtitle', self.kobo_subtitle)
|
fmt('Subtitle', self.kobo_subtitle)
|
||||||
if self.mime:
|
if self.mime:
|
||||||
|
@ -83,7 +83,7 @@ class KOBO(USBMS):
|
|||||||
|
|
||||||
dbversion = 0
|
dbversion = 0
|
||||||
fwversion = (0,0,0)
|
fwversion = (0,0,0)
|
||||||
supported_dbversion = 156
|
supported_dbversion = 158
|
||||||
has_kepubs = False
|
has_kepubs = False
|
||||||
|
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
@ -1349,7 +1349,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 = 157
|
supported_dbversion = 158
|
||||||
min_supported_dbversion = 53
|
min_supported_dbversion = 53
|
||||||
min_dbversion_series = 65
|
min_dbversion_series = 65
|
||||||
min_dbversion_externalid = 65
|
min_dbversion_externalid = 65
|
||||||
@ -1357,11 +1357,12 @@ class KOBOTOUCH(KOBO):
|
|||||||
min_dbversion_images_on_sdcard = 77
|
min_dbversion_images_on_sdcard = 77
|
||||||
min_dbversion_activity = 77
|
min_dbversion_activity = 77
|
||||||
min_dbversion_keywords = 82
|
min_dbversion_keywords = 82
|
||||||
|
min_dbversion_seriesid = 136
|
||||||
|
|
||||||
# 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, 19, 14114)
|
max_supported_fwversion = (4, 20, 14601)
|
||||||
# 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)
|
||||||
@ -1377,11 +1378,13 @@ class KOBOTOUCH(KOBO):
|
|||||||
min_librah20_fwversion = (4, 16, 13337) # "Reviewers" release.
|
min_librah20_fwversion = (4, 16, 13337) # "Reviewers" release.
|
||||||
min_fwversion_epub_location = (4, 17, 13651) # ePub reading location without full contentid.
|
min_fwversion_epub_location = (4, 17, 13651) # ePub reading location without full contentid.
|
||||||
min_fwversion_dropbox = (4, 18, 13737) # The Forma only at this point.
|
min_fwversion_dropbox = (4, 18, 13737) # The Forma only at this point.
|
||||||
|
min_fwversion_serieslist = (4, 20, 14601) # Series list needs the SeriesID to be set.
|
||||||
|
|
||||||
has_kepubs = True
|
has_kepubs = True
|
||||||
|
|
||||||
booklist_class = KTCollectionsBookList
|
booklist_class = KTCollectionsBookList
|
||||||
book_class = Book
|
book_class = Book
|
||||||
|
kobo_series_dict = {}
|
||||||
|
|
||||||
MAX_PATH_LEN = 185 # 250 - (len(" - N3_LIBRARY_SHELF.parsed") + len("F:\.kobo\images\"))
|
MAX_PATH_LEN = 185 # 250 - (len(" - N3_LIBRARY_SHELF.parsed") + len("F:\.kobo\images\"))
|
||||||
KOBO_EXTRA_CSSFILE = 'kobo_extra.css'
|
KOBO_EXTRA_CSSFILE = 'kobo_extra.css'
|
||||||
@ -1610,7 +1613,8 @@ class KOBOTOUCH(KOBO):
|
|||||||
bl_cache[b.lpath] = idx
|
bl_cache[b.lpath] = idx
|
||||||
|
|
||||||
def update_booklist(prefix, path, ContentID, ContentType, MimeType, ImageID,
|
def update_booklist(prefix, path, ContentID, ContentType, MimeType, ImageID,
|
||||||
title, authors, DateCreated, Description, Publisher, series, seriesnumber,
|
title, authors, DateCreated, Description, Publisher,
|
||||||
|
series, seriesnumber, SeriesID, SeriesNumberFloat,
|
||||||
ISBN, Language, Subtitle,
|
ISBN, Language, Subtitle,
|
||||||
readstatus, expired, favouritesindex, accessibility, isdownloaded,
|
readstatus, expired, favouritesindex, accessibility, isdownloaded,
|
||||||
userid, bookshelves
|
userid, bookshelves
|
||||||
@ -1747,10 +1751,16 @@ class KOBOTOUCH(KOBO):
|
|||||||
bl[idx].kobo_metadata = kobo_metadata
|
bl[idx].kobo_metadata = kobo_metadata
|
||||||
bl[idx].kobo_series = series
|
bl[idx].kobo_series = series
|
||||||
bl[idx].kobo_series_number = seriesnumber
|
bl[idx].kobo_series_number = seriesnumber
|
||||||
|
bl[idx].kobo_series_id = SeriesID
|
||||||
bl[idx].kobo_subtitle = Subtitle
|
bl[idx].kobo_subtitle = Subtitle
|
||||||
bl[idx].can_put_on_shelves = allow_shelves
|
bl[idx].can_put_on_shelves = allow_shelves
|
||||||
bl[idx].mime = MimeType
|
bl[idx].mime = MimeType
|
||||||
|
|
||||||
|
if not bl[idx].is_sideloaded and bl[idx].has_kobo_series and SeriesID is not None:
|
||||||
|
if show_debug:
|
||||||
|
debug_print('KoboTouch:update_booklist - Have purchased kepub with series, saving SeriesID=', SeriesID)
|
||||||
|
self.kobo_series_dict[series] = SeriesID
|
||||||
|
|
||||||
if lpath in playlist_map:
|
if lpath in playlist_map:
|
||||||
bl[idx].device_collections = playlist_map.get(lpath,[])
|
bl[idx].device_collections = playlist_map.get(lpath,[])
|
||||||
bl[idx].current_shelves = bookshelves
|
bl[idx].current_shelves = bookshelves
|
||||||
@ -1800,10 +1810,16 @@ class KOBOTOUCH(KOBO):
|
|||||||
book.kobo_metadata = kobo_metadata
|
book.kobo_metadata = kobo_metadata
|
||||||
book.kobo_series = series
|
book.kobo_series = series
|
||||||
book.kobo_series_number = seriesnumber
|
book.kobo_series_number = seriesnumber
|
||||||
|
book.kobo_series_id = SeriesID
|
||||||
book.kobo_subtitle = Subtitle
|
book.kobo_subtitle = Subtitle
|
||||||
book.can_put_on_shelves = allow_shelves
|
book.can_put_on_shelves = allow_shelves
|
||||||
# debug_print('KoboTouch:update_booklist - title=', title, 'book.device_collections', book.device_collections)
|
# debug_print('KoboTouch:update_booklist - title=', title, 'book.device_collections', book.device_collections)
|
||||||
|
|
||||||
|
if not book.is_sideloaded and book.has_kobo_series and SeriesID is not None:
|
||||||
|
if show_debug:
|
||||||
|
debug_print('KoboTouch:update_booklist - Have purchased kepub with series, saving SeriesID=', SeriesID)
|
||||||
|
self.kobo_series_dict[series] = SeriesID
|
||||||
|
|
||||||
if bl.add_book(book, replace_metadata=False):
|
if bl.add_book(book, replace_metadata=False):
|
||||||
changed = True
|
changed = True
|
||||||
if show_debug:
|
if show_debug:
|
||||||
@ -1863,6 +1879,10 @@ class KOBOTOUCH(KOBO):
|
|||||||
columns += ", Series, SeriesNumber, ___UserID, ExternalId, Subtitle"
|
columns += ", Series, SeriesNumber, ___UserID, ExternalId, Subtitle"
|
||||||
else:
|
else:
|
||||||
columns += ', null as Series, null as SeriesNumber, ___UserID, null as ExternalId, null as Subtitle'
|
columns += ', null as Series, null as SeriesNumber, ___UserID, null as ExternalId, null as Subtitle'
|
||||||
|
if self.supports_series_list:
|
||||||
|
columns += ", SeriesID, SeriesNumberFloat"
|
||||||
|
else:
|
||||||
|
columns += ', null as SeriesID, null as SeriesNumberFloat'
|
||||||
|
|
||||||
where_clause = ''
|
where_clause = ''
|
||||||
if self.supports_kobo_archive() or self.supports_overdrive():
|
if self.supports_kobo_archive() or self.supports_overdrive():
|
||||||
@ -1957,7 +1977,8 @@ class KOBOTOUCH(KOBO):
|
|||||||
prefix = self._card_a_prefix if oncard == 'carda' else self._main_prefix
|
prefix = self._card_a_prefix if oncard == 'carda' else self._main_prefix
|
||||||
changed = update_booklist(prefix, path, row['ContentID'], row['ContentType'], row['MimeType'], row['ImageId'],
|
changed = update_booklist(prefix, path, row['ContentID'], row['ContentType'], row['MimeType'], row['ImageId'],
|
||||||
row['Title'], row['Attribution'], row['DateCreated'], row['Description'], row['Publisher'],
|
row['Title'], row['Attribution'], row['DateCreated'], row['Description'], row['Publisher'],
|
||||||
row['Series'], row['SeriesNumber'], row['ISBN'], row['Language'], row['Subtitle'],
|
row['Series'], row['SeriesNumber'], row['SeriesID'], row['SeriesNumberFloat'],
|
||||||
|
row['ISBN'], row['Language'], row['Subtitle'],
|
||||||
row['ReadStatus'], row['___ExpirationStatus'],
|
row['ReadStatus'], row['___ExpirationStatus'],
|
||||||
int(row['FavouritesIndex']), row['Accessibility'], row['IsDownloaded'],
|
int(row['FavouritesIndex']), row['Accessibility'], row['IsDownloaded'],
|
||||||
row['___UserID'], bookshelves
|
row['___UserID'], bookshelves
|
||||||
@ -1972,6 +1993,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
self.dump_bookshelves(connection)
|
self.dump_bookshelves(connection)
|
||||||
else:
|
else:
|
||||||
debug_print("KoboTouch:books - automatically managing metadata")
|
debug_print("KoboTouch:books - automatically managing metadata")
|
||||||
|
debug_print("KoboTouch:books - self.kobo_series_dict=", self.kobo_series_dict)
|
||||||
# Remove books that are no longer in the filesystem. Cache contains
|
# Remove books that are no longer in the filesystem. Cache contains
|
||||||
# indices into the booklist if book not in filesystem, None otherwise
|
# indices into the booklist if book not in filesystem, None otherwise
|
||||||
# Do the operation in reverse order so indices remain valid
|
# Do the operation in reverse order so indices remain valid
|
||||||
@ -3127,7 +3149,6 @@ class KOBOTOUCH(KOBO):
|
|||||||
kobo_series_number = None
|
kobo_series_number = None
|
||||||
series_number_changed = not (kobo_series_number == newmi.series_index)
|
series_number_changed = not (kobo_series_number == newmi.series_index)
|
||||||
|
|
||||||
if series_changed or series_number_changed:
|
|
||||||
if newmi.series is not None:
|
if newmi.series is not None:
|
||||||
new_series = newmi.series
|
new_series = newmi.series
|
||||||
try:
|
try:
|
||||||
@ -3138,10 +3159,19 @@ class KOBOTOUCH(KOBO):
|
|||||||
new_series = None
|
new_series = None
|
||||||
new_series_number = None
|
new_series_number = None
|
||||||
|
|
||||||
|
if series_changed or series_number_changed:
|
||||||
update_values.append(new_series)
|
update_values.append(new_series)
|
||||||
set_clause += ', Series = ? '
|
set_clause += ', Series = ? '
|
||||||
update_values.append(new_series_number)
|
update_values.append(new_series_number)
|
||||||
set_clause += ', SeriesNumber = ? '
|
set_clause += ', SeriesNumber = ? '
|
||||||
|
if self.supports_series_list and book.is_sideloaded:
|
||||||
|
series_id = self.kobo_series_dict.get(new_series, new_series)
|
||||||
|
if not book.kobo_series_id == series_id or series_changed or series_number_changed:
|
||||||
|
update_values.append(series_id)
|
||||||
|
set_clause += ', SeriesID = ? '
|
||||||
|
update_values.append(new_series_number)
|
||||||
|
set_clause += ', SeriesNumberFloat = ? '
|
||||||
|
debug_print("KoboTouch:set_core_metadata Setting SeriesID - new_series='%s', series_id='%s'" % (new_series, series_id))
|
||||||
|
|
||||||
if not series_only:
|
if not series_only:
|
||||||
if not (newmi.title == kobo_metadata.title):
|
if not (newmi.title == kobo_metadata.title):
|
||||||
@ -3537,6 +3567,10 @@ class KOBOTOUCH(KOBO):
|
|||||||
def supports_series(self):
|
def supports_series(self):
|
||||||
return self.dbversion >= self.min_dbversion_series
|
return self.dbversion >= self.min_dbversion_series
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supports_series_list(self):
|
||||||
|
return self.dbversion >= self.min_dbversion_seriesid and self.fwversion >= self.min_fwversion_serieslist
|
||||||
|
|
||||||
def supports_kobo_archive(self):
|
def supports_kobo_archive(self):
|
||||||
return self.dbversion >= self.min_dbversion_archive
|
return self.dbversion >= self.min_dbversion_archive
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user