Kobo driver: Add management of the I'm Reading list on Kobo via an Im_Reading tag in calibre

This commit is contained in:
Kovid Goyal 2010-09-16 18:56:50 -06:00
commit e77eafa751

View File

@ -5,15 +5,16 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Timothy Legge <timlegge at gmail.com> and Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import os
import os, time
import sqlite3 as sqlite
from calibre.devices.usbms.books import BookList
from calibre.devices.kobo.books import Book
from calibre.devices.kobo.books import ImageWrapper
from calibre.devices.mime import mime_type_ext
from calibre.devices.usbms.driver import USBMS
from calibre.devices.usbms.driver import USBMS, debug_print
from calibre import prints
from calibre.devices.usbms.books import CollectionsBookList
class KOBO(USBMS):
@ -21,12 +22,15 @@ class KOBO(USBMS):
gui_name = 'Kobo Reader'
description = _('Communicate with the Kobo Reader')
author = 'Timothy Legge and Kovid Goyal'
version = (1, 0, 4)
version = (1, 0, 6)
supported_platforms = ['windows', 'osx', 'linux']
booklist_class = CollectionsBookList
# Ordered list of supported formats
FORMATS = ['epub', 'pdf']
CAN_SET_METADATA = True
VENDOR_ID = [0x2237]
PRODUCT_ID = [0x4161]
@ -40,6 +44,12 @@ class KOBO(USBMS):
VIRTUAL_BOOK_EXTENSIONS = frozenset(['kobo'])
EXTRA_CUSTOMIZATION_MESSAGE = _('The Kobo supports only one collection '
'currently: the \"Im_Reading\" list. Create a tag called \"Im_Reading\" ')+\
'for automatic management'
EXTRA_CUSTOMIZATION_DEFAULT = ', '.join(['tags'])
def initialize(self):
USBMS.initialize(self)
self.book_class = Book
@ -63,6 +73,8 @@ class KOBO(USBMS):
self._card_b_prefix if oncard == 'cardb' \
else self._main_prefix
self.booklist_class.rebuild_collections = self.rebuild_collections
# get the metadata cache
bl = self.booklist_class(oncard, prefix, self.settings)
need_sync = self.parse_metadata_cache(bl, prefix, self.METADATA_CACHE)
@ -85,9 +97,7 @@ class KOBO(USBMS):
playlist_map = {}
if readstatus == 1:
if lpath not in playlist_map:
playlist_map[lpath] = []
playlist_map[lpath].append("I\'m Reading")
playlist_map[lpath]= "Im_Reading"
path = self.normalize_path(path)
# print "Normalized FileName: " + path
@ -104,14 +114,17 @@ class KOBO(USBMS):
if self.update_metadata_item(bl[idx]):
# print 'update_metadata_item returned true'
changed = True
bl[idx].device_collections = playlist_map.get(lpath, [])
if lpath in playlist_map and \
playlist_map[lpath] not in bl[idx].device_collections:
bl[idx].device_collections.append(playlist_map[lpath])
else:
if ContentType == '6':
book = Book(prefix, lpath, title, authors, mime, date, ContentType, ImageID, size=1048576)
else:
book = self.book_from_path(prefix, lpath, title, authors, mime, date, ContentType, ImageID)
# print 'Update booklist'
book.device_collections = playlist_map.get(book.lpath, [])
book.device_collections = [playlist_map[lpath]] if lpath in playlist_map else []
if bl.add_book(book, replace_metadata=False):
changed = True
except: # Probably a path encoding error
@ -398,3 +411,95 @@ class KOBO(USBMS):
size = os.stat(cls.normalize_path(os.path.join(prefix, lpath))).st_size
book = Book(prefix, lpath, title, authors, mime, date, ContentType, ImageID, size=size, other=mi)
return book
def get_device_paths(self):
paths, prefixes = {}, {}
for prefix, path, source_id in [
('main', 'metadata.calibre', 0),
('card_a', 'metadata.calibre', 1),
('card_b', 'metadata.calibre', 2)
]:
prefix = getattr(self, '_%s_prefix'%prefix)
if prefix is not None and os.path.exists(prefix):
paths[source_id] = os.path.join(prefix, *(path.split('/')))
return paths
def update_device_database_collections(self, booklists, collections_attributes):
# debug_print('Starting update_device_database_collections', collections_attributes)
# Force collections_attributes to be 'tags' as no other is currently supported
# debug_print('KOBO: overriding the provided collections_attributes:', collections_attributes)
collections_attributes = ['tags']
collections = booklists.get_collections(collections_attributes)
# debug_print('Collections', collections)
for category, books in collections.items():
if category == 'Im_Reading':
# Create a connection to the sqlite database
connection = sqlite.connect(self._main_prefix + '.kobo/KoboReader.sqlite')
cursor = connection.cursor()
# Reset Im_Reading list in the database
query= 'update content set ReadStatus=0, FirstTimeReading = \'true\' where BookID is Null'
try:
cursor.execute (query)
except:
debug_print('Database Exception: Unable to reset Im_Reading list')
raise
else:
# debug_print('Commit: Reset Im_Reading list')
connection.commit()
for book in books:
# debug_print('Title:', book.title, 'lpath:', book.path)
book.device_collections = ['Im_Reading']
extension = os.path.splitext(book.path)[1]
ContentType = self.get_content_type_from_extension(extension)
ContentID = self.contentid_from_path(book.path, ContentType)
datelastread = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime())
t = (datelastread,ContentID,)
try:
cursor.execute('update content set ReadStatus=1,FirstTimeReading=\'false\',DateLastRead=? where BookID is Null and ContentID = ?', t)
except:
debug_print('Database Exception: Unable create Im_Reading list')
raise
else:
connection.commit()
# debug_print('Database: Commit create Im_Reading list')
cursor.close()
connection.close()
# debug_print('Finished update_device_database_collections', collections_attributes)
def sync_booklists(self, booklists, end_session=True):
# debug_print('KOBO: started sync_booklists')
paths = self.get_device_paths()
blists = {}
for i in paths:
if booklists[i] is not None:
#debug_print('Booklist: ', i)
blists[i] = booklists[i]
opts = self.settings()
if opts.extra_customization:
collections = [x.lower().strip() for x in
opts.extra_customization.split(',')]
else:
collections = []
#debug_print('KOBO: collection fields:', collections)
for i, blist in blists.items():
self.update_device_database_collections(blist, collections)
USBMS.sync_booklists(self, booklists, end_session=end_session)
#debug_print('KOBO: finished sync_booklists')
def rebuild_collections(self, booklist, oncard):
collections_attributes = []
self.update_device_database_collections(booklist, collections_attributes)