mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Rationalize collections column in device view
This commit is contained in:
parent
a28c63dc1f
commit
036c2fe68c
@ -391,8 +391,8 @@ class BookList(list):
|
|||||||
def __init__(self, oncard, prefix, settings):
|
def __init__(self, oncard, prefix, settings):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def supports_tags(self):
|
def supports_collections(self):
|
||||||
''' Return True if the the device supports tags (collections) for this book list. '''
|
''' Return True if the the device supports collections for this book list. '''
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def add_book(self, book, replace_metadata):
|
def add_book(self, book, replace_metadata):
|
||||||
|
@ -14,6 +14,7 @@ from calibre.devices.prs505 import MEDIA_XML
|
|||||||
from calibre.devices.prs505 import CACHE_XML
|
from calibre.devices.prs505 import CACHE_XML
|
||||||
from calibre.devices.prs505.sony_cache import XMLCache
|
from calibre.devices.prs505.sony_cache import XMLCache
|
||||||
from calibre import __appname__
|
from calibre import __appname__
|
||||||
|
from calibre.devices.usbms.books import CollectionsBookList
|
||||||
|
|
||||||
class PRS505(USBMS):
|
class PRS505(USBMS):
|
||||||
|
|
||||||
@ -23,6 +24,8 @@ class PRS505(USBMS):
|
|||||||
author = 'Kovid Goyal'
|
author = 'Kovid Goyal'
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
path_sep = '/'
|
path_sep = '/'
|
||||||
|
booklist_class = CollectionsBookList
|
||||||
|
|
||||||
|
|
||||||
FORMATS = ['epub', 'lrf', 'lrx', 'rtf', 'pdf', 'txt']
|
FORMATS = ['epub', 'lrf', 'lrx', 'rtf', 'pdf', 'txt']
|
||||||
|
|
||||||
|
@ -97,8 +97,8 @@ class Book(MetaInformation):
|
|||||||
|
|
||||||
class BookList(_BookList):
|
class BookList(_BookList):
|
||||||
|
|
||||||
def supports_tags(self):
|
def supports_collections(self):
|
||||||
return True
|
return False
|
||||||
|
|
||||||
def add_book(self, book, replace_metadata):
|
def add_book(self, book, replace_metadata):
|
||||||
if book not in self:
|
if book not in self:
|
||||||
@ -109,6 +109,15 @@ class BookList(_BookList):
|
|||||||
def remove_book(self, book):
|
def remove_book(self, book):
|
||||||
self.remove(book)
|
self.remove(book)
|
||||||
|
|
||||||
|
def get_collections(self):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
class CollectionsBookList(BookList):
|
||||||
|
|
||||||
|
def supports_collections(self):
|
||||||
|
return True
|
||||||
|
|
||||||
def get_collections(self, collection_attributes):
|
def get_collections(self, collection_attributes):
|
||||||
collections = {}
|
collections = {}
|
||||||
series_categories = set([])
|
series_categories = set([])
|
||||||
|
@ -729,6 +729,17 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
|
|
||||||
class OnDeviceSearch(SearchQueryParser): # {{{
|
class OnDeviceSearch(SearchQueryParser): # {{{
|
||||||
|
|
||||||
|
DEFAULT_LOCATIONS = [
|
||||||
|
'collections',
|
||||||
|
'title',
|
||||||
|
'author',
|
||||||
|
'format',
|
||||||
|
'search',
|
||||||
|
'date',
|
||||||
|
'all',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, model):
|
def __init__(self, model):
|
||||||
SearchQueryParser.__init__(self)
|
SearchQueryParser.__init__(self)
|
||||||
self.model = model
|
self.model = model
|
||||||
@ -738,6 +749,8 @@ class OnDeviceSearch(SearchQueryParser): # {{{
|
|||||||
|
|
||||||
def get_matches(self, location, query):
|
def get_matches(self, location, query):
|
||||||
location = location.lower().strip()
|
location = location.lower().strip()
|
||||||
|
if location == 'authors':
|
||||||
|
location = 'author'
|
||||||
|
|
||||||
matchkind = CONTAINS_MATCH
|
matchkind = CONTAINS_MATCH
|
||||||
if len(query) > 1:
|
if len(query) > 1:
|
||||||
@ -752,14 +765,15 @@ class OnDeviceSearch(SearchQueryParser): # {{{
|
|||||||
if matchkind != REGEXP_MATCH: ### leave case in regexps because it can be significant e.g. \S \W \D
|
if matchkind != REGEXP_MATCH: ### leave case in regexps because it can be significant e.g. \S \W \D
|
||||||
query = query.lower()
|
query = query.lower()
|
||||||
|
|
||||||
if location not in ('title', 'author', 'tag', 'all', 'format'):
|
if location not in self.DEFAULT_LOCATIONS:
|
||||||
return set([])
|
return set([])
|
||||||
matches = set([])
|
matches = set([])
|
||||||
locations = ['title', 'author', 'tag', 'format'] if location == 'all' else [location]
|
all_locs = set(self.DEFAULT_LOCATIONS) - set(['all'])
|
||||||
|
locations = all_locs if location == 'all' else [location]
|
||||||
q = {
|
q = {
|
||||||
'title' : lambda x : getattr(x, 'title').lower(),
|
'title' : lambda x : getattr(x, 'title').lower(),
|
||||||
'author': lambda x: ' & '.join(getattr(x, 'authors')).lower(),
|
'author': lambda x: ' & '.join(getattr(x, 'authors')).lower(),
|
||||||
'tag':lambda x: ','.join(getattr(x, 'tags')).lower(),
|
'collections':lambda x: ','.join(getattr(x, 'device_collections')).lower(),
|
||||||
'format':lambda x: os.path.splitext(x.path)[1].lower()
|
'format':lambda x: os.path.splitext(x.path)[1].lower()
|
||||||
}
|
}
|
||||||
for index, row in enumerate(self.model.db):
|
for index, row in enumerate(self.model.db):
|
||||||
@ -774,7 +788,7 @@ class OnDeviceSearch(SearchQueryParser): # {{{
|
|||||||
else:
|
else:
|
||||||
m = matchkind
|
m = matchkind
|
||||||
|
|
||||||
if locvalue == 'tag':
|
if locvalue == 'collections':
|
||||||
vals = accessor(row).split(',')
|
vals = accessor(row).split(',')
|
||||||
else:
|
else:
|
||||||
vals = [accessor(row)]
|
vals = [accessor(row)]
|
||||||
@ -800,14 +814,14 @@ class DeviceBooksModel(BooksModel): # {{{
|
|||||||
self.sort_history = [self.sorted_on]
|
self.sort_history = [self.sorted_on]
|
||||||
self.unknown = _('Unknown')
|
self.unknown = _('Unknown')
|
||||||
self.column_map = ['inlibrary', 'title', 'authors', 'timestamp', 'size',
|
self.column_map = ['inlibrary', 'title', 'authors', 'timestamp', 'size',
|
||||||
'tags']
|
'collections']
|
||||||
self.headers = {
|
self.headers = {
|
||||||
'inlibrary' : _('In Library'),
|
'inlibrary' : _('In Library'),
|
||||||
'title' : _('Title'),
|
'title' : _('Title'),
|
||||||
'authors' : _('Author(s)'),
|
'authors' : _('Author(s)'),
|
||||||
'timestamp' : _('Date'),
|
'timestamp' : _('Date'),
|
||||||
'size' : _('Size'),
|
'size' : _('Size'),
|
||||||
'tags' : _('Collections')
|
'collections' : _('Collections')
|
||||||
}
|
}
|
||||||
self.marked_for_deletion = {}
|
self.marked_for_deletion = {}
|
||||||
self.search_engine = OnDeviceSearch(self)
|
self.search_engine = OnDeviceSearch(self)
|
||||||
@ -846,7 +860,8 @@ class DeviceBooksModel(BooksModel): # {{{
|
|||||||
flags = QAbstractTableModel.flags(self, index)
|
flags = QAbstractTableModel.flags(self, index)
|
||||||
if index.isValid() and self.editable:
|
if index.isValid() and self.editable:
|
||||||
cname = self.column_map[index.column()]
|
cname = self.column_map[index.column()]
|
||||||
if cname in ('title', 'authors') or (cname == 'tags' and self.db.supports_tags()):
|
if cname in ('title', 'authors') or (cname == 'collection' and \
|
||||||
|
self.db.supports_collections()):
|
||||||
flags |= Qt.ItemIsEditable
|
flags |= Qt.ItemIsEditable
|
||||||
return flags
|
return flags
|
||||||
|
|
||||||
@ -918,7 +933,7 @@ class DeviceBooksModel(BooksModel): # {{{
|
|||||||
'authors' : authorcmp,
|
'authors' : authorcmp,
|
||||||
'size' : sizecmp,
|
'size' : sizecmp,
|
||||||
'timestamp': datecmp,
|
'timestamp': datecmp,
|
||||||
'tags': tagscmp,
|
'collections': tagscmp,
|
||||||
'inlibrary': libcmp,
|
'inlibrary': libcmp,
|
||||||
}[cname]
|
}[cname]
|
||||||
self.map.sort(cmp=fcmp, reverse=descending)
|
self.map.sort(cmp=fcmp, reverse=descending)
|
||||||
@ -1000,14 +1015,15 @@ class DeviceBooksModel(BooksModel): # {{{
|
|||||||
dt = self.db[self.map[row]].datetime
|
dt = self.db[self.map[row]].datetime
|
||||||
dt = dt_factory(dt, assume_utc=True, as_utc=False)
|
dt = dt_factory(dt, assume_utc=True, as_utc=False)
|
||||||
return QVariant(strftime(TIME_FMT, dt.timetuple()))
|
return QVariant(strftime(TIME_FMT, dt.timetuple()))
|
||||||
elif cname == 'tags':
|
elif cname == 'collections':
|
||||||
tags = self.db[self.map[row]].device_collections
|
tags = self.db[self.map[row]].device_collections
|
||||||
if tags:
|
if tags:
|
||||||
return QVariant(', '.join(tags))
|
return QVariant(', '.join(tags))
|
||||||
elif role == Qt.ToolTipRole and index.isValid():
|
elif role == Qt.ToolTipRole and index.isValid():
|
||||||
if self.map[row] in self.indices_to_be_deleted():
|
if self.map[row] in self.indices_to_be_deleted():
|
||||||
return QVariant(_('Marked for deletion'))
|
return QVariant(_('Marked for deletion'))
|
||||||
if cname in ['title', 'authors'] or (cname == 'tags' and self.db.supports_tags()):
|
if cname in ['title', 'authors'] or (cname == 'collections' and \
|
||||||
|
self.db.supports_collections()):
|
||||||
return QVariant(_("Double click to <b>edit</b> me<br><br>"))
|
return QVariant(_("Double click to <b>edit</b> me<br><br>"))
|
||||||
elif role == Qt.DecorationRole and cname == 'inlibrary':
|
elif role == Qt.DecorationRole and cname == 'inlibrary':
|
||||||
if self.db[self.map[row]].in_library:
|
if self.db[self.map[row]].in_library:
|
||||||
|
@ -222,7 +222,6 @@ class BooksView(QTableView): # {{{
|
|||||||
return
|
return
|
||||||
for col, order in reversed(self.cleanup_sort_history(saved_history)[:3]):
|
for col, order in reversed(self.cleanup_sort_history(saved_history)[:3]):
|
||||||
self.sortByColumn(self.column_map.index(col), order)
|
self.sortByColumn(self.column_map.index(col), order)
|
||||||
#self.model().sort_history = saved_history
|
|
||||||
|
|
||||||
def apply_state(self, state):
|
def apply_state(self, state):
|
||||||
h = self.column_header
|
h = self.column_header
|
||||||
|
Loading…
x
Reference in New Issue
Block a user