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
This commit is contained in:
commit
2b40d1dbfb
@ -70,6 +70,7 @@ class Book(Book_):
|
|||||||
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_series_id = None
|
||||||
self.kobo_subtitle = None
|
self.kobo_subtitle = None
|
||||||
|
self.kobo_bookstats = {}
|
||||||
|
|
||||||
if thumbnail_name is not None:
|
if thumbnail_name is not None:
|
||||||
self.thumbnail = ImageWrapper(thumbnail_name)
|
self.thumbnail = ImageWrapper(thumbnail_name)
|
||||||
@ -151,7 +152,7 @@ class KTCollectionsBookList(CollectionsBookList):
|
|||||||
if show_debug: # or len(book.device_collections) > 0:
|
if show_debug: # or len(book.device_collections) > 0:
|
||||||
debug_print('KTCollectionsBookList:get_collections - tsval=', tsval, "book.title=", book.title, "book.title_sort=", book.title_sort)
|
debug_print('KTCollectionsBookList:get_collections - tsval=', tsval, "book.title=", book.title, "book.title_sort=", book.title_sort)
|
||||||
debug_print('KTCollectionsBookList:get_collections - book.device_collections=', book.device_collections)
|
debug_print('KTCollectionsBookList:get_collections - book.device_collections=', book.device_collections)
|
||||||
# debug_print(book)
|
# debug_print(book)
|
||||||
# Make sure we can identify this book via the lpath
|
# Make sure we can identify this book via the lpath
|
||||||
lpath = getattr(book, 'lpath', None)
|
lpath = getattr(book, 'lpath', None)
|
||||||
if lpath is None:
|
if lpath is None:
|
||||||
@ -221,7 +222,7 @@ class KTCollectionsBookList(CollectionsBookList):
|
|||||||
val = val.decode(preferred_encoding, 'replace')
|
val = val.decode(preferred_encoding, 'replace')
|
||||||
if isinstance(val, (list, tuple)):
|
if isinstance(val, (list, tuple)):
|
||||||
val = list(val)
|
val = list(val)
|
||||||
# debug_print("KTCollectionsBookList:get_collections - val is list=", val)
|
# debug_print("KTCollectionsBookList:get_collections - val is list=", val)
|
||||||
elif fm is not None and fm['datatype'] == 'series':
|
elif fm is not None and fm['datatype'] == 'series':
|
||||||
val = [orig_val]
|
val = [orig_val]
|
||||||
elif fm is not None and fm['datatype'] == 'rating':
|
elif fm is not None and fm['datatype'] == 'rating':
|
||||||
|
@ -36,6 +36,7 @@ from polyglot.builtins import iteritems, itervalues, string_or_bytes
|
|||||||
|
|
||||||
EPUB_EXT = '.epub'
|
EPUB_EXT = '.epub'
|
||||||
KEPUB_EXT = '.kepub'
|
KEPUB_EXT = '.kepub'
|
||||||
|
KOBO_ROOT_DIR_NAME = ".kobo"
|
||||||
|
|
||||||
DEFAULT_COVER_LETTERBOX_COLOR = '#000000'
|
DEFAULT_COVER_LETTERBOX_COLOR = '#000000'
|
||||||
|
|
||||||
@ -84,10 +85,11 @@ class KOBO(USBMS):
|
|||||||
|
|
||||||
dbversion = 0
|
dbversion = 0
|
||||||
fwversion = (0,0,0)
|
fwversion = (0,0,0)
|
||||||
|
_device_version_info = None
|
||||||
# The firmware for these devices is not being updated. But the Kobo desktop application
|
# The firmware for these devices is not being updated. But the Kobo desktop application
|
||||||
# will update the database if the device is connected. The database structure is completely
|
# will update the database if the device is connected. The database structure is completely
|
||||||
# backwardly compatible.
|
# backwardly compatible.
|
||||||
supported_dbversion = 162
|
supported_dbversion = 169
|
||||||
has_kepubs = False
|
has_kepubs = False
|
||||||
|
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
@ -170,9 +172,14 @@ class KOBO(USBMS):
|
|||||||
def initialize(self):
|
def initialize(self):
|
||||||
USBMS.initialize(self)
|
USBMS.initialize(self)
|
||||||
self.dbversion = 7
|
self.dbversion = 7
|
||||||
|
self._device_version_info = None
|
||||||
|
|
||||||
|
def eject(self):
|
||||||
|
self._device_version_info = None
|
||||||
|
super().eject()
|
||||||
|
|
||||||
def device_database_path(self):
|
def device_database_path(self):
|
||||||
return self.normalize_path(self._main_prefix + '.kobo/KoboReader.sqlite')
|
return os.path.join(self._main_prefix, KOBO_ROOT_DIR_NAME, 'KoboReader.sqlite')
|
||||||
|
|
||||||
def device_database_connection(self, use_row_factory=False):
|
def device_database_connection(self, use_row_factory=False):
|
||||||
import apsw
|
import apsw
|
||||||
@ -197,14 +204,29 @@ class KOBO(USBMS):
|
|||||||
|
|
||||||
return dbversion
|
return dbversion
|
||||||
|
|
||||||
|
def device_version_info(self):
|
||||||
|
debug_print("device_version_info - start")
|
||||||
|
if not self._device_version_info:
|
||||||
|
version_file = os.path.join(self._main_prefix, KOBO_ROOT_DIR_NAME, "version")
|
||||||
|
debug_print(f"device_version_info - version_file={version_file}")
|
||||||
|
if os.path.isfile(version_file):
|
||||||
|
debug_print("device_version_info - have opened version_file")
|
||||||
|
vf = open(version_file, "r")
|
||||||
|
self._device_version_info = vf.read().strip().split(",")
|
||||||
|
vf.close()
|
||||||
|
debug_print("device_version_info - self._device_version_info=", self._device_version_info)
|
||||||
|
return self._device_version_info
|
||||||
|
|
||||||
|
def device_serial_no(self):
|
||||||
|
return self.device_version_info()[0]
|
||||||
|
|
||||||
def get_firmware_version(self):
|
def get_firmware_version(self):
|
||||||
# Determine the firmware version
|
# Determine the firmware version
|
||||||
try:
|
try:
|
||||||
with lopen(self.normalize_path(self._main_prefix + '.kobo/version'), 'rb') as f:
|
fwversion = self.device_version_info()[2]
|
||||||
fwversion = f.readline().split(b',')[2]
|
fwversion = tuple(int(x) for x in fwversion.split('.'))
|
||||||
fwversion = tuple(int(x) for x in fwversion.split(b'.'))
|
except Exception as e:
|
||||||
except Exception:
|
debug_print(f"Kobo::get_firmware_version - didn't get firmware version from file' - Exception: {e}")
|
||||||
debug_print("Kobo::get_firmware_version - didn't get firmware version from file'")
|
|
||||||
fwversion = (0,0,0)
|
fwversion = (0,0,0)
|
||||||
|
|
||||||
return fwversion
|
return fwversion
|
||||||
@ -292,10 +314,10 @@ class KOBO(USBMS):
|
|||||||
if idx is not None:
|
if idx is not None:
|
||||||
bl_cache[lpath] = None
|
bl_cache[lpath] = None
|
||||||
if ImageID is not None:
|
if ImageID is not None:
|
||||||
imagename = self.normalize_path(self._main_prefix + '.kobo/images/' + ImageID + ' - NickelBookCover.parsed')
|
imagename = self.normalize_path(self._main_prefix + KOBO_ROOT_DIR_NAME + '/images/' + ImageID + ' - NickelBookCover.parsed')
|
||||||
if not os.path.exists(imagename):
|
if not os.path.exists(imagename):
|
||||||
# Try the Touch version if the image does not exist
|
# Try the Touch version if the image does not exist
|
||||||
imagename = self.normalize_path(self._main_prefix + '.kobo/images/' + ImageID + ' - N3_LIBRARY_FULL.parsed')
|
imagename = self.normalize_path(self._main_prefix + KOBO_ROOT_DIR_NAME + '/images/' + ImageID + ' - N3_LIBRARY_FULL.parsed')
|
||||||
|
|
||||||
# print "Image name Normalized: " + imagename
|
# print "Image name Normalized: " + imagename
|
||||||
if not os.path.exists(imagename):
|
if not os.path.exists(imagename):
|
||||||
@ -505,7 +527,7 @@ class KOBO(USBMS):
|
|||||||
|
|
||||||
def delete_images(self, ImageID, book_path):
|
def delete_images(self, ImageID, book_path):
|
||||||
if ImageID is not None:
|
if ImageID is not None:
|
||||||
path_prefix = '.kobo/images/'
|
path_prefix = KOBO_ROOT_DIR_NAME + '/images/'
|
||||||
path = self._main_prefix + path_prefix + ImageID
|
path = self._main_prefix + path_prefix + ImageID
|
||||||
|
|
||||||
file_endings = (' - iPhoneThumbnail.parsed', ' - bbMediumGridList.parsed', ' - NickelBookCover.parsed', ' - N3_LIBRARY_FULL.parsed',
|
file_endings = (' - iPhoneThumbnail.parsed', ' - bbMediumGridList.parsed', ' - NickelBookCover.parsed', ' - N3_LIBRARY_FULL.parsed',
|
||||||
@ -622,7 +644,7 @@ class KOBO(USBMS):
|
|||||||
ContentID = ContentID.replace(self._main_prefix, '')
|
ContentID = ContentID.replace(self._main_prefix, '')
|
||||||
else:
|
else:
|
||||||
ContentID = path
|
ContentID = path
|
||||||
ContentID = ContentID.replace(self._main_prefix + self.normalize_path('.kobo/kepub/'), '')
|
ContentID = ContentID.replace(self._main_prefix + self.normalize_path(KOBO_ROOT_DIR_NAME + '/kepub/'), '')
|
||||||
|
|
||||||
if self._card_a_prefix is not None:
|
if self._card_a_prefix is not None:
|
||||||
ContentID = ContentID.replace(self._card_a_prefix, '')
|
ContentID = ContentID.replace(self._card_a_prefix, '')
|
||||||
@ -684,7 +706,7 @@ class KOBO(USBMS):
|
|||||||
if path.startswith("file:///mnt/onboard/"):
|
if path.startswith("file:///mnt/onboard/"):
|
||||||
path = self._main_prefix + path.replace("file:///mnt/onboard/", '')
|
path = self._main_prefix + path.replace("file:///mnt/onboard/", '')
|
||||||
else:
|
else:
|
||||||
path = self._main_prefix + '.kobo/kepub/' + path
|
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/kepub/' + path
|
||||||
# print "Internal: " + path
|
# print "Internal: " + path
|
||||||
else:
|
else:
|
||||||
# if path.startswith("file:///mnt/onboard/"):
|
# if path.startswith("file:///mnt/onboard/"):
|
||||||
@ -1037,7 +1059,7 @@ class KOBO(USBMS):
|
|||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
if ImageID is not None:
|
if ImageID is not None:
|
||||||
path_prefix = '.kobo/images/'
|
path_prefix = KOBO_ROOT_DIR_NAME + '/images/'
|
||||||
path = self._main_prefix + path_prefix + ImageID
|
path = self._main_prefix + path_prefix + ImageID
|
||||||
|
|
||||||
file_endings = {' - iPhoneThumbnail.parsed':(103,150),
|
file_endings = {' - iPhoneThumbnail.parsed':(103,150),
|
||||||
@ -1355,7 +1377,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 = 166
|
supported_dbversion = 169
|
||||||
min_supported_dbversion = 53
|
min_supported_dbversion = 53
|
||||||
min_dbversion_series = 65
|
min_dbversion_series = 65
|
||||||
min_dbversion_externalid = 65
|
min_dbversion_externalid = 65
|
||||||
@ -1364,11 +1386,12 @@ class KOBOTOUCH(KOBO):
|
|||||||
min_dbversion_activity = 77
|
min_dbversion_activity = 77
|
||||||
min_dbversion_keywords = 82
|
min_dbversion_keywords = 82
|
||||||
min_dbversion_seriesid = 136
|
min_dbversion_seriesid = 136
|
||||||
|
min_dbversion_bookstats = 169
|
||||||
|
|
||||||
# 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, 31, 19086)
|
max_supported_fwversion = (4, 32, 19501)
|
||||||
# The following document firmware versions where new function or devices were added.
|
# The following document firmware 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)
|
||||||
@ -1390,6 +1413,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
min_libra2_fwversion = (4, 29, 18730)
|
min_libra2_fwversion = (4, 29, 18730)
|
||||||
min_sage_fwversion = (4, 29, 18730)
|
min_sage_fwversion = (4, 29, 18730)
|
||||||
min_fwversion_audiobooks = (4, 29, 18730)
|
min_fwversion_audiobooks = (4, 29, 18730)
|
||||||
|
min_fwversion_bookstats = (4, 32, 19501)
|
||||||
|
|
||||||
has_kepubs = True
|
has_kepubs = True
|
||||||
|
|
||||||
@ -1636,7 +1660,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
series, seriesnumber, SeriesID, SeriesNumberFloat,
|
series, seriesnumber, SeriesID, SeriesNumberFloat,
|
||||||
ISBN, Language, Subtitle,
|
ISBN, Language, Subtitle,
|
||||||
readstatus, expired, favouritesindex, accessibility, isdownloaded,
|
readstatus, expired, favouritesindex, accessibility, isdownloaded,
|
||||||
userid, bookshelves
|
userid, bookshelves, book_stats=None
|
||||||
):
|
):
|
||||||
show_debug = self.is_debugging_title(title)
|
show_debug = self.is_debugging_title(title)
|
||||||
# show_debug = authors == 'L. Frank Baum'
|
# show_debug = authors == 'L. Frank Baum'
|
||||||
@ -1781,6 +1805,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
bl[idx].kobo_series_id = SeriesID
|
bl[idx].kobo_series_id = SeriesID
|
||||||
bl[idx].kobo_series_number_float = SeriesNumberFloat
|
bl[idx].kobo_series_number_float = SeriesNumberFloat
|
||||||
bl[idx].kobo_subtitle = Subtitle
|
bl[idx].kobo_subtitle = Subtitle
|
||||||
|
bl[idx].kobo_bookstats = book_stats
|
||||||
bl[idx].can_put_on_shelves = allow_shelves
|
bl[idx].can_put_on_shelves = allow_shelves
|
||||||
bl[idx].mime = MimeType
|
bl[idx].mime = MimeType
|
||||||
|
|
||||||
@ -1841,6 +1866,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
book.kobo_series_id = SeriesID
|
book.kobo_series_id = SeriesID
|
||||||
book.kobo_series_number_float = SeriesNumberFloat
|
book.kobo_series_number_float = SeriesNumberFloat
|
||||||
book.kobo_subtitle = Subtitle
|
book.kobo_subtitle = Subtitle
|
||||||
|
book.kobo_bookstats = book_stats
|
||||||
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)
|
||||||
|
|
||||||
@ -1912,6 +1938,10 @@ class KOBOTOUCH(KOBO):
|
|||||||
columns += ", SeriesID, SeriesNumberFloat"
|
columns += ", SeriesID, SeriesNumberFloat"
|
||||||
else:
|
else:
|
||||||
columns += ', null as SeriesID, null as SeriesNumberFloat'
|
columns += ', null as SeriesID, null as SeriesNumberFloat'
|
||||||
|
if self.supports_bookstats:
|
||||||
|
columns += ", StorePages, StoreWordCount, StoreTimeToReadLowerEstimate, StoreTimeToReadUpperEstimate"
|
||||||
|
else:
|
||||||
|
columns += ', null as StorePages, null as StoreWordCount, null as StoreTimeToReadLowerEstimate, null as StoreTimeToReadUpperEstimate'
|
||||||
|
|
||||||
where_clause = ''
|
where_clause = ''
|
||||||
if self.supports_kobo_archive() or self.supports_overdrive():
|
if self.supports_kobo_archive() or self.supports_overdrive():
|
||||||
@ -2010,7 +2040,13 @@ class KOBOTOUCH(KOBO):
|
|||||||
row['ISBN'], row['Language'], row['Subtitle'],
|
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,
|
||||||
|
book_stats={
|
||||||
|
'StorePages': row['StorePages'],
|
||||||
|
'StoreWordCount': row['StoreWordCount'],
|
||||||
|
'StoreTimeToReadLowerEstimate': row['StoreTimeToReadLowerEstimate'],
|
||||||
|
'StoreTimeToReadUpperEstimate': row['StoreTimeToReadUpperEstimate']
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if changed:
|
if changed:
|
||||||
@ -2082,7 +2118,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
else:
|
else:
|
||||||
if (ContentType == "6" or ContentType == "10"):
|
if (ContentType == "6" or ContentType == "10"):
|
||||||
if (MimeType == 'application/octet-stream'): # Audiobooks purchased from Kobo are in a different location.
|
if (MimeType == 'application/octet-stream'): # Audiobooks purchased from Kobo are in a different location.
|
||||||
path = self._main_prefix + '.kobo/audiobook/' + path
|
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/audiobook/' + path
|
||||||
elif path.startswith("file:///mnt/onboard/"):
|
elif path.startswith("file:///mnt/onboard/"):
|
||||||
path = self._main_prefix + path.replace("file:///mnt/onboard/", '')
|
path = self._main_prefix + path.replace("file:///mnt/onboard/", '')
|
||||||
elif path.startswith("file:///mnt/sd/"):
|
elif path.startswith("file:///mnt/sd/"):
|
||||||
@ -2090,7 +2126,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
elif externalId:
|
elif externalId:
|
||||||
path = self._card_a_prefix + 'koboExtStorage/kepub/' + path
|
path = self._card_a_prefix + 'koboExtStorage/kepub/' + path
|
||||||
else:
|
else:
|
||||||
path = self._main_prefix + '.kobo/kepub/' + path
|
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/kepub/' + path
|
||||||
else: # Should never get here, but, just in case...
|
else: # Should never get here, but, just in case...
|
||||||
# if path.startswith("file:///mnt/onboard/"):
|
# if path.startswith("file:///mnt/onboard/"):
|
||||||
path = path.replace("file:///mnt/onboard/", self._main_prefix)
|
path = path.replace("file:///mnt/onboard/", self._main_prefix)
|
||||||
@ -2387,7 +2423,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
ContentID = ContentID.replace(self._main_prefix, '')
|
ContentID = ContentID.replace(self._main_prefix, '')
|
||||||
elif not extension:
|
elif not extension:
|
||||||
ContentID = path
|
ContentID = path
|
||||||
ContentID = ContentID.replace(self._main_prefix + self.normalize_path('.kobo/kepub/'), '')
|
ContentID = ContentID.replace(self._main_prefix + self.normalize_path(KOBO_ROOT_DIR_NAME + '/kepub/'), '')
|
||||||
else:
|
else:
|
||||||
ContentID = path
|
ContentID = path
|
||||||
ContentID = ContentID.replace(self._main_prefix, "file:///mnt/onboard/")
|
ContentID = ContentID.replace(self._main_prefix, "file:///mnt/onboard/")
|
||||||
@ -2663,7 +2699,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
path_prefix = 'koboExtStorage/images-cache/' if self.supports_images_tree() else 'koboExtStorage/images/'
|
path_prefix = 'koboExtStorage/images-cache/' if self.supports_images_tree() else 'koboExtStorage/images/'
|
||||||
path = os.path.join(self._card_a_prefix, path_prefix)
|
path = os.path.join(self._card_a_prefix, path_prefix)
|
||||||
else:
|
else:
|
||||||
path_prefix = '.kobo-images/' if self.supports_images_tree() else '.kobo/images/'
|
path_prefix = '.kobo-images/' if self.supports_images_tree() else KOBO_ROOT_DIR_NAME + '/images/'
|
||||||
path = os.path.join(self._main_prefix, path_prefix)
|
path = os.path.join(self._main_prefix, path_prefix)
|
||||||
|
|
||||||
if self.supports_images_tree() and imageId:
|
if self.supports_images_tree() and imageId:
|
||||||
@ -3173,11 +3209,28 @@ class KOBOTOUCH(KOBO):
|
|||||||
debug_print("KoboTouch:set_series - end")
|
debug_print("KoboTouch:set_series - end")
|
||||||
|
|
||||||
def set_core_metadata(self, connection, book, series_only=False):
|
def set_core_metadata(self, connection, book, series_only=False):
|
||||||
# debug_print('KoboTouch:set_core_metadata book="%s"' % book.title)
|
debug_print('KoboTouch:set_core_metadata book="%s"' % book.title)
|
||||||
show_debug = self.is_debugging_title(book.title)
|
show_debug = self.is_debugging_title(book.title)
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print(f'KoboTouch:set_core_metadata book="{book}", \nseries_only="{series_only}"')
|
debug_print(f'KoboTouch:set_core_metadata book="{book}", \nseries_only="{series_only}"')
|
||||||
|
|
||||||
|
def generate_update_from_template(book, update_values, set_clause, column_name, new_value=None, template=None, current_value=None):
|
||||||
|
if template is None or template == '':
|
||||||
|
new_value = None
|
||||||
|
else:
|
||||||
|
new_value = new_value if len(new_value.strip()) else None
|
||||||
|
if new_value is not None and new_value.startswith("PLUGBOARD TEMPLATE ERROR"):
|
||||||
|
debug_print("KoboTouch:generate_update_from_template template error - template='%s'" % template)
|
||||||
|
debug_print("KoboTouch:generate_update_from_template - new_value=", new_value)
|
||||||
|
|
||||||
|
debug_print(f"KoboTouch:generate_update_from_template - {book.title} - column_name='{column_name}', current_value='{current_value}', new_value='{new_value}'")
|
||||||
|
if (new_value is not None and \
|
||||||
|
(current_value is None or new_value != current_value) ) or \
|
||||||
|
(new_value is None and current_value is not None):
|
||||||
|
update_values.append(new_value)
|
||||||
|
set_clause.append(column_name)
|
||||||
|
|
||||||
|
|
||||||
plugboard = None
|
plugboard = None
|
||||||
if self.plugboard_func and not series_only:
|
if self.plugboard_func and not series_only:
|
||||||
if book.contentID.endswith('.kepub.epub') or not os.path.splitext(book.contentID)[1]:
|
if book.contentID.endswith('.kepub.epub') or not os.path.splitext(book.contentID)[1]:
|
||||||
@ -3198,7 +3251,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
|
|
||||||
update_query = 'UPDATE content SET '
|
update_query = 'UPDATE content SET '
|
||||||
update_values = []
|
update_values = []
|
||||||
set_clause = ''
|
set_clause = []
|
||||||
changes_found = False
|
changes_found = False
|
||||||
kobo_metadata = book.kobo_metadata
|
kobo_metadata = book.kobo_metadata
|
||||||
|
|
||||||
@ -3229,9 +3282,9 @@ class KOBOTOUCH(KOBO):
|
|||||||
|
|
||||||
if series_changed or series_number_changed:
|
if series_changed or series_number_changed:
|
||||||
update_values.append(new_series)
|
update_values.append(new_series)
|
||||||
set_clause += ', Series = ? '
|
set_clause.append('Series')
|
||||||
update_values.append(new_series_number)
|
update_values.append(new_series_number)
|
||||||
set_clause += ', SeriesNumber = ? '
|
set_clause.append('SeriesNumber')
|
||||||
if self.supports_series_list and book.is_sideloaded:
|
if self.supports_series_list and book.is_sideloaded:
|
||||||
series_id = self.kobo_series_dict.get(new_series, new_series)
|
series_id = self.kobo_series_dict.get(new_series, new_series)
|
||||||
try:
|
try:
|
||||||
@ -3245,50 +3298,63 @@ class KOBOTOUCH(KOBO):
|
|||||||
or not kobo_series_id == series_id \
|
or not kobo_series_id == series_id \
|
||||||
or not kobo_series_number_float == newmi.series_index:
|
or not kobo_series_number_float == newmi.series_index:
|
||||||
update_values.append(series_id)
|
update_values.append(series_id)
|
||||||
set_clause += ', SeriesID = ? '
|
set_clause.append('SeriesID')
|
||||||
update_values.append(newmi.series_index)
|
update_values.append(newmi.series_index)
|
||||||
set_clause += ', SeriesNumberFloat = ? '
|
set_clause.append('SeriesNumberFloat')
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print(f"KoboTouch:set_core_metadata Setting SeriesID - new_series='{new_series}', series_id='{series_id}'")
|
debug_print(f"KoboTouch:set_core_metadata Setting SeriesID - new_series='{new_series}', series_id='{series_id}'")
|
||||||
|
|
||||||
if not series_only:
|
if not series_only:
|
||||||
|
pb = []
|
||||||
|
if self.subtitle_template is not None:
|
||||||
|
pb.append((self.subtitle_template, 'subtitle'))
|
||||||
|
if self.bookstats_pagecount_template is not None:
|
||||||
|
pb.append((self.bookstats_pagecount_template, 'bookstats_pagecount'))
|
||||||
|
if self.bookstats_wordcount_template is not None:
|
||||||
|
pb.append((self.bookstats_wordcount_template, 'bookstats_wordcount'))
|
||||||
|
if self.bookstats_timetoread_upper_template is not None:
|
||||||
|
pb.append((self.bookstats_timetoread_upper_template, 'bookstats_timetoread_upper'))
|
||||||
|
if self.bookstats_timetoread_lower_template is not None:
|
||||||
|
pb.append((self.bookstats_timetoread_lower_template, 'bookstats_timetoread_lower'))
|
||||||
|
if show_debug:
|
||||||
|
debug_print(f"KoboTouch:set_core_metadata templates being used - pb='{pb}'")
|
||||||
|
book.template_to_attribute(book, pb)
|
||||||
|
|
||||||
if not (newmi.title == kobo_metadata.title):
|
if not (newmi.title == kobo_metadata.title):
|
||||||
update_values.append(newmi.title)
|
update_values.append(newmi.title)
|
||||||
set_clause += ', Title = ? '
|
set_clause.append('Title')
|
||||||
|
|
||||||
if not (authors_to_string(newmi.authors) == authors_to_string(kobo_metadata.authors)):
|
if not (authors_to_string(newmi.authors) == authors_to_string(kobo_metadata.authors)):
|
||||||
update_values.append(authors_to_string(newmi.authors))
|
update_values.append(authors_to_string(newmi.authors))
|
||||||
set_clause += ', Attribution = ? '
|
set_clause.append('Attribution')
|
||||||
|
|
||||||
if not (newmi.publisher == kobo_metadata.publisher):
|
if not (newmi.publisher == kobo_metadata.publisher):
|
||||||
update_values.append(newmi.publisher)
|
update_values.append(newmi.publisher)
|
||||||
set_clause += ', Publisher = ? '
|
set_clause.append('Publisher')
|
||||||
|
|
||||||
if not (newmi.pubdate == kobo_metadata.pubdate):
|
if not (newmi.pubdate == kobo_metadata.pubdate):
|
||||||
pubdate_string = strftime(self.TIMESTAMP_STRING, newmi.pubdate) if newmi.pubdate else None
|
pubdate_string = strftime(self.TIMESTAMP_STRING, newmi.pubdate) if newmi.pubdate else None
|
||||||
update_values.append(pubdate_string)
|
update_values.append(pubdate_string)
|
||||||
set_clause += ', DateCreated = ? '
|
set_clause.append('DateCreated')
|
||||||
|
|
||||||
if not (newmi.comments == kobo_metadata.comments):
|
if not (newmi.comments == kobo_metadata.comments):
|
||||||
update_values.append(newmi.comments)
|
update_values.append(newmi.comments)
|
||||||
set_clause += ', Description = ? '
|
set_clause.append('Description')
|
||||||
|
|
||||||
if not (newmi.isbn == kobo_metadata.isbn):
|
if not (newmi.isbn == kobo_metadata.isbn):
|
||||||
update_values.append(newmi.isbn)
|
update_values.append(newmi.isbn)
|
||||||
set_clause += ', ISBN = ? '
|
set_clause.append('ISBN')
|
||||||
|
|
||||||
library_language = normalize_languages(kobo_metadata.languages, newmi.languages)
|
library_language = normalize_languages(kobo_metadata.languages, newmi.languages)
|
||||||
library_language = library_language[0] if library_language is not None and len(library_language) > 0 else None
|
library_language = library_language[0] if library_language is not None and len(library_language) > 0 else None
|
||||||
if not (library_language == kobo_metadata.language):
|
if not (library_language == kobo_metadata.language):
|
||||||
update_values.append(library_language)
|
update_values.append(library_language)
|
||||||
set_clause += ', Language = ? '
|
set_clause.append('Language')
|
||||||
|
|
||||||
if self.update_subtitle:
|
if self.update_subtitle:
|
||||||
if self.subtitle_template is None or self.subtitle_template == '':
|
if self.subtitle_template is None or self.subtitle_template == '':
|
||||||
new_subtitle = None
|
new_subtitle = None
|
||||||
else:
|
else:
|
||||||
pb = [(self.subtitle_template, 'subtitle')]
|
|
||||||
book.template_to_attribute(book, pb)
|
|
||||||
new_subtitle = book.subtitle if len(book.subtitle.strip()) else None
|
new_subtitle = book.subtitle if len(book.subtitle.strip()) else None
|
||||||
if new_subtitle is not None and new_subtitle.startswith("PLUGBOARD TEMPLATE ERROR"):
|
if new_subtitle is not None and new_subtitle.startswith("PLUGBOARD TEMPLATE ERROR"):
|
||||||
debug_print("KoboTouch:set_core_metadata subtitle template error - self.subtitle_template='%s'" % self.subtitle_template)
|
debug_print("KoboTouch:set_core_metadata subtitle template error - self.subtitle_template='%s'" % self.subtitle_template)
|
||||||
@ -3297,16 +3363,51 @@ class KOBOTOUCH(KOBO):
|
|||||||
if (new_subtitle is not None and (book.kobo_subtitle is None or book.subtitle != book.kobo_subtitle)) or \
|
if (new_subtitle is not None and (book.kobo_subtitle is None or book.subtitle != book.kobo_subtitle)) or \
|
||||||
(new_subtitle is None and book.kobo_subtitle is not None):
|
(new_subtitle is None and book.kobo_subtitle is not None):
|
||||||
update_values.append(new_subtitle)
|
update_values.append(new_subtitle)
|
||||||
set_clause += ', Subtitle = ? '
|
set_clause.append('Subtitle')
|
||||||
|
|
||||||
|
if self.update_bookstats:
|
||||||
|
if self.bookstats_pagecount_template is not None:
|
||||||
|
current_bookstats_pagecount = book.kobo_bookstats.get('StorePages', None)
|
||||||
|
generate_update_from_template(book, update_values, set_clause,
|
||||||
|
column_name='StorePages',
|
||||||
|
template=self.bookstats_pagecount_template,
|
||||||
|
new_value=book.bookstats_pagecount,
|
||||||
|
current_value=current_bookstats_pagecount
|
||||||
|
)
|
||||||
|
if self.bookstats_wordcount_template is not None:
|
||||||
|
current_bookstats_wordcount = book.kobo_bookstats.get('StoreWordCount', None)
|
||||||
|
generate_update_from_template(book, update_values, set_clause,
|
||||||
|
column_name='StoreWordCount',
|
||||||
|
template=self.bookstats_wordcount_template,
|
||||||
|
new_value=book.bookstats_wordcount,
|
||||||
|
current_value=current_bookstats_wordcount
|
||||||
|
)
|
||||||
|
if self.bookstats_timetoread_upper_template is not None:
|
||||||
|
current_bookstats_timetoread_upper = book.kobo_bookstats.get('StoreTimeToReadUpperEstimate', None)
|
||||||
|
generate_update_from_template(book, update_values, set_clause,
|
||||||
|
column_name='StoreTimeToReadUpperEstimate',
|
||||||
|
template=self.bookstats_timetoread_upper_template,
|
||||||
|
new_value=book.bookstats_timetoread_upper,
|
||||||
|
current_value=current_bookstats_timetoread_upper
|
||||||
|
)
|
||||||
|
if self.bookstats_timetoread_lower_template is not None:
|
||||||
|
current_bookstats_timetoread_lower = book.kobo_bookstats.get('StoreTimeToReadLowerEstimate', None)
|
||||||
|
generate_update_from_template(book, update_values, set_clause,
|
||||||
|
column_name='StoreTimeToReadLowerEstimate',
|
||||||
|
template=self.bookstats_timetoread_lower_template,
|
||||||
|
new_value=book.bookstats_timetoread_lower,
|
||||||
|
current_value=current_bookstats_timetoread_lower
|
||||||
|
)
|
||||||
|
|
||||||
if len(set_clause) > 0:
|
if len(set_clause) > 0:
|
||||||
update_query += set_clause[1:]
|
update_query += ', '.join([col_name + ' = ?' for col_name in set_clause])
|
||||||
changes_found = True
|
changes_found = True
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print('KoboTouch:set_core_metadata set_clause="%s"' % set_clause)
|
debug_print('KoboTouch:set_core_metadata set_clause="%s"' % set_clause)
|
||||||
debug_print('KoboTouch:set_core_metadata update_values="%s"' % update_values)
|
debug_print('KoboTouch:set_core_metadata update_values="%s"' % update_values)
|
||||||
|
debug_print('KoboTouch:set_core_metadata update_values="%s"' % update_query)
|
||||||
if changes_found:
|
if changes_found:
|
||||||
update_query += 'WHERE ContentID = ? AND BookID IS NULL'
|
update_query += ' WHERE ContentID = ? AND BookID IS NULL'
|
||||||
update_values.append(book.contentID)
|
update_values.append(book.contentID)
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
try:
|
try:
|
||||||
@ -3317,6 +3418,8 @@ class KOBOTOUCH(KOBO):
|
|||||||
self.core_metadata_set += 1
|
self.core_metadata_set += 1
|
||||||
except:
|
except:
|
||||||
debug_print(' Database Exception: Unable to set the core metadata')
|
debug_print(' Database Exception: Unable to set the core metadata')
|
||||||
|
debug_print(f' Query was: {update_query}')
|
||||||
|
debug_print(f' Values were: {update_values}')
|
||||||
raise
|
raise
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
@ -3324,6 +3427,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print("KoboTouch:set_core_metadata - end")
|
debug_print("KoboTouch:set_core_metadata - end")
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def config_widget(cls):
|
def config_widget(cls):
|
||||||
# TODO: Cleanup the following
|
# TODO: Cleanup the following
|
||||||
@ -3387,6 +3491,11 @@ class KOBOTOUCH(KOBO):
|
|||||||
c.add_opt('update_device_metadata', default=True)
|
c.add_opt('update_device_metadata', default=True)
|
||||||
c.add_opt('update_subtitle', default=False)
|
c.add_opt('update_subtitle', default=False)
|
||||||
c.add_opt('subtitle_template', default=None)
|
c.add_opt('subtitle_template', default=None)
|
||||||
|
c.add_opt('update_bookstats', default=False)
|
||||||
|
c.add_opt('bookstats_wordcount_template', default=None)
|
||||||
|
c.add_opt('bookstats_pagecount_template', default=None)
|
||||||
|
c.add_opt('bookstats_timetoread_upper_template', default=None)
|
||||||
|
c.add_opt('bookstats_timetoread_lower_template', default=None)
|
||||||
|
|
||||||
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('override_kobo_replace_existing', default=True) # Overriding the replace behaviour is how the driver has always worked.
|
||||||
@ -3644,6 +3753,43 @@ class KOBOTOUCH(KOBO):
|
|||||||
subtitle_template = subtitle_template.strip() if subtitle_template is not None else None
|
subtitle_template = subtitle_template.strip() if subtitle_template is not None else None
|
||||||
return subtitle_template
|
return subtitle_template
|
||||||
|
|
||||||
|
@property
|
||||||
|
def update_bookstats(self):
|
||||||
|
# Subtitle was added to the database at the same time as the series support.
|
||||||
|
return self.update_device_metadata and self.supports_bookstats and self.get_pref('update_bookstats')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bookstats_wordcount_template(self):
|
||||||
|
if not self.update_bookstats:
|
||||||
|
return None
|
||||||
|
bookstats_wordcount_template = self.get_pref('bookstats_wordcount_template')
|
||||||
|
bookstats_wordcount_template = bookstats_wordcount_template.strip() if bookstats_wordcount_template is not None else None
|
||||||
|
return bookstats_wordcount_template
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bookstats_pagecount_template(self):
|
||||||
|
if not self.update_bookstats:
|
||||||
|
return None
|
||||||
|
bookstats_pagecount_template = self.get_pref('bookstats_pagecount_template')
|
||||||
|
bookstats_pagecount_template = bookstats_pagecount_template.strip() if bookstats_pagecount_template is not None else None
|
||||||
|
return bookstats_pagecount_template
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bookstats_timetoread_lower_template(self):
|
||||||
|
if not self.update_bookstats:
|
||||||
|
return None
|
||||||
|
bookstats_timetoread_lower_template = self.get_pref('bookstats_timetoread_lower_template')
|
||||||
|
bookstats_timetoread_lower_template = bookstats_timetoread_lower_template.strip() if bookstats_timetoread_lower_template is not None else None
|
||||||
|
return bookstats_timetoread_lower_template
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bookstats_timetoread_upper_template(self):
|
||||||
|
if not self.update_bookstats:
|
||||||
|
return None
|
||||||
|
bookstats_timetoread_upper_template = self.get_pref('bookstats_timetoread_upper_template')
|
||||||
|
bookstats_timetoread_upper_template = bookstats_timetoread_upper_template.strip() if bookstats_timetoread_upper_template is not None else None
|
||||||
|
return bookstats_timetoread_upper_template
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def update_core_metadata(self):
|
def update_core_metadata(self):
|
||||||
return self.update_device_metadata and self.get_pref('update_core_metadata')
|
return self.update_device_metadata and self.get_pref('update_core_metadata')
|
||||||
@ -3682,6 +3828,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_bookstats(self):
|
||||||
|
return self.fwversion >= self.min_fwversion_bookstats and self.dbversion >= self.min_dbversion_bookstats
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supports_series_list(self):
|
def supports_series_list(self):
|
||||||
return self.dbversion >= self.min_dbversion_seriesid and self.fwversion >= self.min_fwversion_serieslist
|
return self.dbversion >= self.min_dbversion_seriesid and self.fwversion >= self.min_fwversion_serieslist
|
||||||
|
@ -120,6 +120,11 @@ class KOBOTOUCHConfig(TabbedDeviceConfig):
|
|||||||
p['update_purchased_kepubs'] = self.update_purchased_kepubs
|
p['update_purchased_kepubs'] = self.update_purchased_kepubs
|
||||||
p['subtitle_template'] = self.subtitle_template
|
p['subtitle_template'] = self.subtitle_template
|
||||||
p['update_subtitle'] = self.update_subtitle
|
p['update_subtitle'] = self.update_subtitle
|
||||||
|
p['update_bookstats'] = self.update_bookstats
|
||||||
|
p['bookstats_wordcount_template'] = self.bookstats_wordcount_template
|
||||||
|
p['bookstats_pagecount_template'] = self.bookstats_pagecount_template
|
||||||
|
p['bookstats_timetoread_upper_template'] = self.bookstats_timetoread_upper_template
|
||||||
|
p['bookstats_timetoread_lower_template'] = self.bookstats_timetoread_lower_template
|
||||||
|
|
||||||
p['modify_css'] = self.modify_css
|
p['modify_css'] = self.modify_css
|
||||||
p['override_kobo_replace_existing'] = self.override_kobo_replace_existing
|
p['override_kobo_replace_existing'] = self.override_kobo_replace_existing
|
||||||
@ -560,28 +565,88 @@ class MetadataGroupBox(DeviceOptionsGroupBox):
|
|||||||
"If the template is empty, the subtitle will be cleared."
|
"If the template is empty, the subtitle will be cleared."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
self.update_bookstats_checkbox = create_checkbox(
|
||||||
|
_("Book stats"),
|
||||||
|
_('Update the book stats '),
|
||||||
|
device.get_pref('update_bookstats')
|
||||||
|
)
|
||||||
|
self.bookstats_wordcount_template_edit = TemplateConfig(
|
||||||
|
device.get_pref('bookstats_wordcount_template'),
|
||||||
|
label=_("Words:"),
|
||||||
|
tooltip=_("Enter a template to use to set the word count for the book. "
|
||||||
|
"If the template is empty, the word count will be cleared."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.bookstats_pagecount_template_edit = TemplateConfig(
|
||||||
|
device.get_pref('bookstats_pagecount_template'),
|
||||||
|
label=_("Pages:"),
|
||||||
|
tooltip=_("Enter a template to use to set the page count for the book. "
|
||||||
|
"If the template is empty, the page count will be cleared."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.options_layout.addWidget(self.update_series_checkbox, 0, 0, 1, 2)
|
self.bookstats_timetoread_label = QLabel(_('Hours to read estimates:'))
|
||||||
self.options_layout.addWidget(self.update_core_metadata_checkbox, 1, 0, 1, 2)
|
self.bookstats_timetoread_upper_template_edit = TemplateConfig(
|
||||||
self.options_layout.addWidget(self.update_subtitle_checkbox, 2, 0, 1, 1)
|
device.get_pref('bookstats_timetoread_upper_template'),
|
||||||
self.options_layout.addWidget(self.subtitle_template_edit, 2, 1, 1, 1)
|
label=_("Upper:"),
|
||||||
self.options_layout.addWidget(self.update_purchased_kepubs_checkbox, 3, 0, 1, 2)
|
tooltip=_("Enter a template to use to set the upper estimate of the time to read for the book. "
|
||||||
|
"The estimate is in hours. "
|
||||||
|
"If the template is empty, the time will be cleared."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.bookstats_timetoread_lower_template_edit = TemplateConfig(
|
||||||
|
device.get_pref('bookstats_timetoread_lower_template'),
|
||||||
|
label=_("Lower:"),
|
||||||
|
tooltip=_("Enter a template to use to set the lower estimate of the time to read for the book. "
|
||||||
|
"The estimate is in hours. "
|
||||||
|
"If the template is empty, the time will be cleared."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
line = 0
|
||||||
|
self.options_layout.addWidget(self.update_series_checkbox, line, 0, 1, 4)
|
||||||
|
line += 1
|
||||||
|
self.options_layout.addWidget(self.update_core_metadata_checkbox, line, 0, 1, 4)
|
||||||
|
line += 1
|
||||||
|
self.options_layout.addWidget(self.update_subtitle_checkbox, line, 0, 1, 2)
|
||||||
|
self.options_layout.addWidget(self.subtitle_template_edit, line, 2, 1, 2)
|
||||||
|
line += 1
|
||||||
|
self.options_layout.addWidget(self.update_bookstats_checkbox, line, 0, 1, 2)
|
||||||
|
self.options_layout.addWidget(self.bookstats_wordcount_template_edit, line, 2, 1, 1)
|
||||||
|
self.options_layout.addWidget(self.bookstats_pagecount_template_edit, line, 3, 1, 1)
|
||||||
|
line += 1
|
||||||
|
self.options_layout.addWidget(self.bookstats_timetoread_label, line, 1, 1, 1)
|
||||||
|
self.options_layout.addWidget(self.bookstats_timetoread_lower_template_edit, line, 2, 1, 1)
|
||||||
|
self.options_layout.addWidget(self.bookstats_timetoread_upper_template_edit, line, 3, 1, 1)
|
||||||
|
line += 1
|
||||||
|
self.options_layout.addWidget(self.update_purchased_kepubs_checkbox, line, 0, 1, 4)
|
||||||
|
|
||||||
self.update_core_metadata_checkbox.clicked.connect(self.update_core_metadata_checkbox_clicked)
|
self.update_core_metadata_checkbox.clicked.connect(self.update_core_metadata_checkbox_clicked)
|
||||||
self.update_subtitle_checkbox.clicked.connect(self.update_subtitle_checkbox_clicked)
|
self.update_subtitle_checkbox.clicked.connect(self.update_subtitle_checkbox_clicked)
|
||||||
|
self.update_bookstats_checkbox.clicked.connect(self.update_bookstats_checkbox_clicked)
|
||||||
self.update_core_metadata_checkbox_clicked(device.get_pref('update_core_metadata'))
|
self.update_core_metadata_checkbox_clicked(device.get_pref('update_core_metadata'))
|
||||||
self.update_subtitle_checkbox_clicked(device.get_pref('update_subtitle'))
|
self.update_subtitle_checkbox_clicked(device.get_pref('update_subtitle'))
|
||||||
|
self.update_bookstats_checkbox_clicked(device.get_pref('update_bookstats'))
|
||||||
|
|
||||||
def update_core_metadata_checkbox_clicked(self, checked):
|
def update_core_metadata_checkbox_clicked(self, checked):
|
||||||
self.update_series_checkbox.setEnabled(not checked)
|
self.update_series_checkbox.setEnabled(not checked)
|
||||||
self.subtitle_template_edit.setEnabled(checked)
|
self.subtitle_template_edit.setEnabled(checked)
|
||||||
self.update_subtitle_checkbox.setEnabled(checked)
|
self.update_subtitle_checkbox.setEnabled(checked)
|
||||||
|
self.update_bookstats_checkbox.setEnabled(checked)
|
||||||
self.update_subtitle_checkbox_clicked(self.update_subtitle)
|
self.update_subtitle_checkbox_clicked(self.update_subtitle)
|
||||||
|
self.update_bookstats_checkbox_clicked(self.update_bookstats)
|
||||||
self.update_purchased_kepubs_checkbox.setEnabled(checked)
|
self.update_purchased_kepubs_checkbox.setEnabled(checked)
|
||||||
|
|
||||||
def update_subtitle_checkbox_clicked(self, checked):
|
def update_subtitle_checkbox_clicked(self, checked):
|
||||||
self.subtitle_template_edit.setEnabled(checked and self.update_core_metadata)
|
self.subtitle_template_edit.setEnabled(checked and self.update_core_metadata)
|
||||||
|
|
||||||
|
def update_bookstats_checkbox_clicked(self, checked):
|
||||||
|
self.bookstats_timetoread_label.setEnabled(checked and self.update_bookstats and self.update_core_metadata)
|
||||||
|
self.bookstats_wordcount_template_edit.setEnabled(checked and self.update_bookstats and self.update_core_metadata)
|
||||||
|
self.bookstats_pagecount_template_edit.setEnabled(checked and self.update_bookstats and self.update_core_metadata)
|
||||||
|
self.bookstats_timetoread_upper_template_edit.setEnabled(checked and self.update_bookstats and self.update_core_metadata)
|
||||||
|
self.bookstats_timetoread_lower_template_edit.setEnabled(checked and self.update_bookstats and self.update_core_metadata)
|
||||||
|
|
||||||
def edit_template(self):
|
def edit_template(self):
|
||||||
t = TemplateDialog(self, self.template)
|
t = TemplateDialog(self, self.template)
|
||||||
t.setWindowTitle(_('Edit template'))
|
t.setWindowTitle(_('Edit template'))
|
||||||
@ -591,6 +656,14 @@ class MetadataGroupBox(DeviceOptionsGroupBox):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
if self.update_subtitle and not self.subtitle_template_edit.validate():
|
if self.update_subtitle and not self.subtitle_template_edit.validate():
|
||||||
return False
|
return False
|
||||||
|
if self.update_bookstats and not self.bookstats_pagecount_template_edit.validate():
|
||||||
|
return False
|
||||||
|
if self.update_bookstats and not self.bookstats_wordcount_template_edit.validate():
|
||||||
|
return False
|
||||||
|
if self.update_bookstats and not self.bookstats_timetoread_upper_template_edit.validate():
|
||||||
|
return False
|
||||||
|
if self.update_bookstats and not self.bookstats_timetoread_lower_template_edit.validate():
|
||||||
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -617,20 +690,43 @@ class MetadataGroupBox(DeviceOptionsGroupBox):
|
|||||||
def update_subtitle(self):
|
def update_subtitle(self):
|
||||||
return self.update_subtitle_checkbox.isChecked()
|
return self.update_subtitle_checkbox.isChecked()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def update_bookstats(self):
|
||||||
|
return self.update_bookstats_checkbox.isChecked()
|
||||||
|
@property
|
||||||
|
def bookstats_pagecount_template(self):
|
||||||
|
return self.bookstats_pagecount_template_edit.template
|
||||||
|
@property
|
||||||
|
def bookstats_wordcount_template(self):
|
||||||
|
return self.bookstats_wordcount_template_edit.template
|
||||||
|
@property
|
||||||
|
def bookstats_timetoread_lower_template(self):
|
||||||
|
return self.bookstats_timetoread_lower_template_edit.template
|
||||||
|
@property
|
||||||
|
def bookstats_timetoread_upper_template(self):
|
||||||
|
return self.bookstats_timetoread_upper_template_edit.template
|
||||||
|
|
||||||
|
|
||||||
|
from calibre.gui2.dialogs.template_line_editor import TemplateLineEditor
|
||||||
|
|
||||||
class TemplateConfig(QWidget): # {{{
|
class TemplateConfig(QWidget): # {{{
|
||||||
|
|
||||||
def __init__(self, val, tooltip=None):
|
def __init__(self, val, label=None, tooltip=None):
|
||||||
QWidget.__init__(self)
|
super().__init__()
|
||||||
self.t = t = QLineEdit(self)
|
self.l = l = QGridLayout(self)
|
||||||
|
self.setLayout(l)
|
||||||
|
col = 0
|
||||||
|
if label is not None:
|
||||||
|
l.addWidget(QLabel(label), 0, col, 1, 1)
|
||||||
|
col += 1
|
||||||
|
self.t = t = TemplateLineEditor(self)
|
||||||
t.setText(val or '')
|
t.setText(val or '')
|
||||||
t.setCursorPosition(0)
|
t.setCursorPosition(0)
|
||||||
self.setMinimumWidth(300)
|
self.setMinimumWidth(300)
|
||||||
self.l = l = QGridLayout(self)
|
l.addWidget(t, 0, col, 1, 1)
|
||||||
self.setLayout(l)
|
col += 1
|
||||||
l.addWidget(t, 1, 0, 1, 1)
|
|
||||||
b = self.b = QPushButton(_('&Template editor'))
|
b = self.b = QPushButton(_('&Template editor'))
|
||||||
l.addWidget(b, 1, 1, 1, 1)
|
l.addWidget(b, 0, col, 1, 1)
|
||||||
b.clicked.connect(self.edit_template)
|
b.clicked.connect(self.edit_template)
|
||||||
self.setToolTip(tooltip)
|
self.setToolTip(tooltip)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user