mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Ondevice works with Sony PRS-300
This commit is contained in:
parent
41755c20ef
commit
afadcc7a1b
@ -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):
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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():
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -100,6 +100,7 @@ class SearchQueryParser(object):
|
|||||||
'search',
|
'search',
|
||||||
'date',
|
'date',
|
||||||
'pubdate',
|
'pubdate',
|
||||||
|
'ondevice',
|
||||||
'all',
|
'all',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user