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 " + \
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):

View File

@ -979,54 +979,62 @@ class DeviceGUI(object):
if memory and 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]
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 = re.sub('(?u)\W|[_]', '', db_title)
au = self.library_view.model().db.authors(index, index_is_id)
db_authors = au.lower() if au else ''
db_authors = re.sub('(?u)\W|[_]', '', db_authors)
for i, l in enumerate(self.booklists()):
for book in l:
book_title = book.title.lower() if book.title else ''
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
break
d = self.book_on_device_cache[i].get(db_title, None)
if d and (index in d['db_ids'] or db_authors in d['authors']):
loc[i] = True
break
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.
Returns the book's id in the library.
Set the 'in_library' attribute for all books on a device to True if a
book on the device is in the library, else False
'''
bl = []
if oncard == 'carda':
bl = self.booklists()[1]
elif oncard == 'cardb':
bl = self.booklists()[2]
else:
bl = self.booklists()[0]
book = bl[index]
book_title = book.title.lower() if book.title else ''
book_title = re.sub('(?u)\W|[_]', '', book_title)
book_authors = authors_to_string(book.authors).lower() if book.authors else ''
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 book.uuid and self.library_view.model().db.uuid(book.application_id, index_is_id=True) == book.uuid:
# return book.application_id
# First build a cache of the library, so the search isn't On**2
cache = {}
for id, title in self.library_view.model().db.all_titles():
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
au = self.library_view.model().db.authors(id, index_is_id=True)
authors = au.lower() if au else ''
authors = re.sub('(?u)\W|[_]', '', authors)
cache[title+authors] = id
# 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 = re.sub('(?u)\W|[_]', '', book_title)
book_authors = authors_to_string(book.authors).lower() if book.authors else ''
book_authors = re.sub('(?u)\W|[_]', '', book_authors)
if cache.get(book_title + book_authors, None) is not None:
book.in_library = True
else:
book.in_library = False

View File

@ -1268,6 +1268,8 @@ class DeviceBooksModel(BooksModel):
def set_book_in_library_func(self, func, loc):
self.book_in_library = func
self.loc = loc
# Not convinced that this should be here ...
func(self.db)
def mark_for_deletion(self, job, 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)
return cmp(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)
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
@ -1429,7 +1431,7 @@ class DeviceBooksModel(BooksModel):
if role == Qt.EditRole:
return QVariant(au)
authors = string_to_authors(au)
return QVariant("\n".join(authors))
return QVariant(" & ".join(authors))
elif col == 2:
size = self.db[self.map[row]].size
return QVariant(BooksView.human_readable(size))
@ -1442,9 +1444,8 @@ class DeviceBooksModel(BooksModel):
if tags:
return QVariant(', '.join(tags))
elif col == 5:
if self.book_in_library:
if self.book_in_library(self.map[row], self.loc) != None:
return QVariant(_("True"))
return QVariant(_('Yes')) \
if self.db[self.map[row]].in_library else QVariant(_('No'))
elif role == Qt.TextAlignmentRole and index.column() in [2, 3]:
return QVariant(Qt.AlignRight | Qt.AlignVCenter)
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:
self.hide_windows()
self.stack.setCurrentIndex(0)
self.book_on_device(None, reset=True)
db.set_book_on_device_func(self.book_on_device)
self.library_view.set_database(db)
self.library_view.model().set_book_on_device_func(self.book_on_device)
@ -993,13 +994,13 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
return
mainlist, cardalist, cardblist = job.result
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.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_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)
for view in (self.memory_view, self.card_a_view, self.card_b_view):
view.sortByColumn(3, Qt.DescendingOrder)
@ -1007,6 +1008,10 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
if not view.restore_column_widths():
view.resizeColumnsToContents()
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_catalogs()
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
def refresh_ondevice_info(self, clear_flags = False):
# self.library_view.model().db.set_all_ondevice('')
# 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.book_on_device(None, reset=True)
self.library_view.model().refresh()
############################################################################
############################################################################
######################### Fetch annotations ################################
def fetch_annotations(self, *args):
@ -2246,6 +2246,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
def library_moved(self, newloc):
if newloc is None: return
db = LibraryDatabase2(newloc)
self.book_on_device(None, reset=True)
db.set_book_on_device_func(self.book_on_device)
self.library_view.set_database(db)
self.library_view.model().set_book_on_device_func(self.book_on_device)

View File

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

View File

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