Ondevice works with Sony PRS-300

This commit is contained in:
Charles Haley 2010-05-09 10:38:30 +01:00
parent 41755c20ef
commit afadcc7a1b
6 changed files with 71 additions and 52 deletions

View File

@ -46,6 +46,14 @@ class Book(object):
return self.title.encode('utf-8') + " by " + \ return self.title.encode('utf-8') + " by " + \
self.authors.encode('utf-8') + " at " + self.path.encode('utf-8') self.authors.encode('utf-8') + " at " + self.path.encode('utf-8')
@dynamic_property
def db_id(self):
doc = '''The database id in the application database that this file corresponds to'''
def fget(self):
match = re.search(r'_(\d+)$', self.rpath.rpartition('.')[0])
if match:
return int(match.group(1))
return property(fget=fget, doc=doc)
class BookList(_BookList): class BookList(_BookList):

View File

@ -979,54 +979,62 @@ class DeviceGUI(object):
if memory and memory[1]: if memory and memory[1]:
self.library_view.model().delete_books_by_id(memory[1]) self.library_view.model().delete_books_by_id(memory[1])
def book_on_device(self, index, index_is_id=False, format=None): def book_on_device(self, index, index_is_id=False, format=None, reset=False):
loc = [None, None, None] loc = [None, None, None]
if reset:
self.book_on_device_cache = None
return
if self.book_on_device_cache is None:
self.book_on_device_cache = []
for i, l in enumerate(self.booklists()):
self.book_on_device_cache.append({})
for book in l:
book_title = book.title.lower() if book.title else ''
book_title = re.sub('(?u)\W|[_]', '', book_title)
if book_title not in self.book_on_device_cache[i]:
self.book_on_device_cache[i][book_title] = \
{'authors':set(), 'db_ids':set()}
book_authors = authors_to_string(book.authors).lower()
book_authors = re.sub('(?u)\W|[_]', '', book_authors)
self.book_on_device_cache[i][book_title]['authors'].add(book_authors)
self.book_on_device_cache[i][book_title]['db_ids'].add(book.db_id)
db_title = self.library_view.model().db.title(index, index_is_id).lower() db_title = self.library_view.model().db.title(index, index_is_id).lower()
db_title = re.sub('(?u)\W|[_]', '', db_title) db_title = re.sub('(?u)\W|[_]', '', db_title)
au = self.library_view.model().db.authors(index, index_is_id) au = self.library_view.model().db.authors(index, index_is_id)
db_authors = au.lower() if au else '' db_authors = au.lower() if au else ''
db_authors = re.sub('(?u)\W|[_]', '', db_authors) db_authors = re.sub('(?u)\W|[_]', '', db_authors)
for i, l in enumerate(self.booklists()): for i, l in enumerate(self.booklists()):
for book in l: d = self.book_on_device_cache[i].get(db_title, None)
book_title = book.title.lower() if book.title else '' if d and (index in d['db_ids'] or db_authors in d['authors']):
book_title = re.sub('(?u)\W|[_]', '', book_title)
book_authors = authors_to_string(book.authors).lower()
book_authors = re.sub('(?u)\W|[_]', '', book_authors)
if book_title == db_title and book_authors == db_authors:
loc[i] = True loc[i] = True
break break
return loc return loc
def book_in_library(self, index, oncard=None): def set_books_in_library(self, booklist):
''' '''
Used to determine if a book on the device is in the library. Set the 'in_library' attribute for all books on a device to True if a
Returns the book's id in the library. book on the device is in the library, else False
''' '''
bl = [] # First build a cache of the library, so the search isn't On**2
if oncard == 'carda': cache = {}
bl = self.booklists()[1] for id, title in self.library_view.model().db.all_titles():
elif oncard == 'cardb': title = re.sub('(?u)\W|[_]', '', title.lower())
bl = self.booklists()[2] au = self.library_view.model().db.authors(id, index_is_id=True)
else: authors = au.lower() if au else ''
bl = self.booklists()[0] authors = re.sub('(?u)\W|[_]', '', authors)
cache[title+authors] = id
book = bl[index] # Now iterate through all the books on the device, setting the in_library field
for book in booklist:
book_title = book.title.lower() if book.title else '' book_title = book.title.lower() if book.title else ''
book_title = re.sub('(?u)\W|[_]', '', book_title) book_title = re.sub('(?u)\W|[_]', '', book_title)
book_authors = authors_to_string(book.authors).lower() if book.authors else '' book_authors = authors_to_string(book.authors).lower() if book.authors else ''
book_authors = re.sub('(?u)\W|[_]', '', book_authors) book_authors = re.sub('(?u)\W|[_]', '', book_authors)
# if getattr(book, 'application_id', None) != None and self.library_view.model().db.has_id(book.application_id): if cache.get(book_title + book_authors, None) is not None:
# if book.uuid and self.library_view.model().db.uuid(book.application_id, index_is_id=True) == book.uuid: book.in_library = True
# return book.application_id else:
for id, title in self.library_view.model().db.all_titles(): book.in_library = False
title = re.sub('(?u)\W|[_]', '', title.lower())
if title == book_title:
au = self.library_view.model().db.authors(id, index_is_id=True)
authors = au.lower() if au else ''
authors = re.sub('(?u)\W|[_]', '', authors)
if authors == book_authors:
return id
return None

View File

@ -1268,6 +1268,8 @@ class DeviceBooksModel(BooksModel):
def set_book_in_library_func(self, func, loc): def set_book_in_library_func(self, func, loc):
self.book_in_library = func self.book_in_library = func
self.loc = loc self.loc = loc
# Not convinced that this should be here ...
func(self.db)
def mark_for_deletion(self, job, rows): def mark_for_deletion(self, job, rows):
self.marked_for_deletion[job] = self.indices(rows) self.marked_for_deletion[job] = self.indices(rows)
@ -1356,7 +1358,7 @@ class DeviceBooksModel(BooksModel):
x, y = ','.join(self.db[x].tags), ','.join(self.db[y].tags) x, y = ','.join(self.db[x].tags), ','.join(self.db[y].tags)
return cmp(x, y) return cmp(x, y)
def libcmp(x, y): def libcmp(x, y):
x, y = self.book_in_library(self.map[x], self.loc), self.book_in_library(self.map[y], self.loc) x, y = self.db[x].in_library, self.db[y].in_library
return cmp(x, y) return cmp(x, y)
fcmp = strcmp('title_sorter') if col == 0 else strcmp('authors') if col == 1 else \ fcmp = strcmp('title_sorter') if col == 0 else strcmp('authors') if col == 1 else \
sizecmp if col == 2 else datecmp if col == 3 else tagscmp if col == 4 else libcmp sizecmp if col == 2 else datecmp if col == 3 else tagscmp if col == 4 else libcmp
@ -1429,7 +1431,7 @@ class DeviceBooksModel(BooksModel):
if role == Qt.EditRole: if role == Qt.EditRole:
return QVariant(au) return QVariant(au)
authors = string_to_authors(au) authors = string_to_authors(au)
return QVariant("\n".join(authors)) return QVariant(" & ".join(authors))
elif col == 2: elif col == 2:
size = self.db[self.map[row]].size size = self.db[self.map[row]].size
return QVariant(BooksView.human_readable(size)) return QVariant(BooksView.human_readable(size))
@ -1442,9 +1444,8 @@ class DeviceBooksModel(BooksModel):
if tags: if tags:
return QVariant(', '.join(tags)) return QVariant(', '.join(tags))
elif col == 5: elif col == 5:
if self.book_in_library: return QVariant(_('Yes')) \
if self.book_in_library(self.map[row], self.loc) != None: if self.db[self.map[row]].in_library else QVariant(_('No'))
return QVariant(_("True"))
elif role == Qt.TextAlignmentRole and index.column() in [2, 3]: elif role == Qt.TextAlignmentRole and index.column() in [2, 3]:
return QVariant(Qt.AlignRight | Qt.AlignVCenter) return QVariant(Qt.AlignRight | Qt.AlignVCenter)
elif role == Qt.ToolTipRole and index.isValid(): elif role == Qt.ToolTipRole and index.isValid():

View File

@ -520,6 +520,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
if self.system_tray_icon.isVisible() and opts.start_in_tray: if self.system_tray_icon.isVisible() and opts.start_in_tray:
self.hide_windows() self.hide_windows()
self.stack.setCurrentIndex(0) self.stack.setCurrentIndex(0)
self.book_on_device(None, reset=True)
db.set_book_on_device_func(self.book_on_device) db.set_book_on_device_func(self.book_on_device)
self.library_view.set_database(db) self.library_view.set_database(db)
self.library_view.model().set_book_on_device_func(self.book_on_device) self.library_view.model().set_book_on_device_func(self.book_on_device)
@ -993,13 +994,13 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
return return
mainlist, cardalist, cardblist = job.result mainlist, cardalist, cardblist = job.result
self.memory_view.set_database(mainlist) self.memory_view.set_database(mainlist)
self.memory_view.model().set_book_in_library_func(self.book_in_library, 'main') self.memory_view.model().set_book_in_library_func(self.set_books_in_library, 'main')
self.memory_view.set_editable(self.device_manager.device.CAN_SET_METADATA) self.memory_view.set_editable(self.device_manager.device.CAN_SET_METADATA)
self.card_a_view.set_database(cardalist) self.card_a_view.set_database(cardalist)
self.card_a_view.model().set_book_in_library_func(self.book_in_library, 'carda') self.card_a_view.model().set_book_in_library_func(self.set_books_in_library, 'carda')
self.card_a_view.set_editable(self.device_manager.device.CAN_SET_METADATA) self.card_a_view.set_editable(self.device_manager.device.CAN_SET_METADATA)
self.card_b_view.set_database(cardblist) self.card_b_view.set_database(cardblist)
self.card_b_view.model().set_book_in_library_func(self.book_in_library, 'cardb') self.card_b_view.model().set_book_in_library_func(self.set_books_in_library, 'cardb')
self.card_b_view.set_editable(self.device_manager.device.CAN_SET_METADATA) self.card_b_view.set_editable(self.device_manager.device.CAN_SET_METADATA)
for view in (self.memory_view, self.card_a_view, self.card_b_view): for view in (self.memory_view, self.card_a_view, self.card_b_view):
view.sortByColumn(3, Qt.DescendingOrder) view.sortByColumn(3, Qt.DescendingOrder)
@ -1007,6 +1008,10 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
if not view.restore_column_widths(): if not view.restore_column_widths():
view.resizeColumnsToContents() view.resizeColumnsToContents()
view.resize_on_select = not view.isVisible() view.resize_on_select = not view.isVisible()
if view.model().rowCount(None) > 1:
view.resizeRowToContents(0)
height = view.rowHeight(0)
view.verticalHeader().setDefaultSectionSize(height)
self.sync_news() self.sync_news()
self.sync_catalogs() self.sync_catalogs()
self.refresh_ondevice_info() self.refresh_ondevice_info()
@ -1014,15 +1019,10 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
############################################################################ ############################################################################
### Force the library view to refresh, taking into consideration books information ### Force the library view to refresh, taking into consideration books information
def refresh_ondevice_info(self, clear_flags = False): def refresh_ondevice_info(self, clear_flags = False):
# self.library_view.model().db.set_all_ondevice('') self.book_on_device(None, reset=True)
# if not clear_flags:
# for id in self.library_view.model().db:
# self.library_view.model().db.set_book_on_device_string(id, index_is_id=True))
self.library_view.model().refresh() self.library_view.model().refresh()
############################################################################ ############################################################################
############################################################################
######################### Fetch annotations ################################ ######################### Fetch annotations ################################
def fetch_annotations(self, *args): def fetch_annotations(self, *args):
@ -2246,6 +2246,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
def library_moved(self, newloc): def library_moved(self, newloc):
if newloc is None: return if newloc is None: return
db = LibraryDatabase2(newloc) db = LibraryDatabase2(newloc)
self.book_on_device(None, reset=True)
db.set_book_on_device_func(self.book_on_device) db.set_book_on_device_func(self.book_on_device)
self.library_view.set_database(db) self.library_view.set_database(db)
self.library_view.model().set_book_on_device_func(self.book_on_device) self.library_view.model().set_book_on_device_func(self.book_on_device)

View File

@ -370,7 +370,7 @@ class ResultCache(SearchQueryParser):
location += 's' location += 's'
all = ('title', 'authors', 'publisher', 'tags', 'comments', 'series', all = ('title', 'authors', 'publisher', 'tags', 'comments', 'series',
'formats', 'isbn', 'rating', 'cover') 'formats', 'isbn', 'rating', 'cover', 'ondevice')
MAP = {} MAP = {}
for x in all: # get the db columns for the standard searchables for x in all: # get the db columns for the standard searchables

View File

@ -100,6 +100,7 @@ class SearchQueryParser(object):
'search', 'search',
'date', 'date',
'pubdate', 'pubdate',
'ondevice',
'all', 'all',
] ]