mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
First pass at converting db2.get_categories to return a complete dict
This commit is contained in:
parent
4946a2f2ad
commit
3b557de4c7
@ -199,8 +199,8 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
|
||||
categories_orig = [_('Authors'), _('Series'), _('Formats'), _('Publishers'),
|
||||
_('Ratings'), _('News'), _('Tags')]
|
||||
row_map_orig = ['author', 'series', 'format', 'publisher', 'rating',
|
||||
'news', 'tag']
|
||||
row_map_orig = ['authors', 'series', 'formats', 'publishers', 'ratings',
|
||||
'news', 'tags']
|
||||
tags_categories_start= 7
|
||||
search_keys=['search', _('Searches')]
|
||||
|
||||
@ -264,8 +264,8 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
self.cat_icon_map.append(self.cat_icon_map_orig[i])
|
||||
|
||||
# Clean up the author's tags, getting rid of the '|' characters
|
||||
if data['author'] is not None:
|
||||
for t in data['author']:
|
||||
if data['authors'] is not None:
|
||||
for t in data['authors']:
|
||||
t.name = t.name.replace('|', ',')
|
||||
|
||||
# Now do the user-defined categories. There is a time/space tradeoff here.
|
||||
|
@ -144,8 +144,8 @@ class CustomColumns(object):
|
||||
for i, v in self.custom_column_num_map.items():
|
||||
if v['normalized']:
|
||||
tn = 'custom_column_{0}'.format(i)
|
||||
self.tag_browser_categories[tn] = [v['label'], 'value']
|
||||
self.tag_browser_datatype[v['label']] = v['datatype']
|
||||
self.tag_browser_categories[v['label']] = {'table':tn, 'column':'value', 'type':v['datatype'], 'name':v['name']}
|
||||
#self.tag_browser_datatype[v['label']] = v['datatype']
|
||||
|
||||
def get_custom(self, idx, label=None, num=None, index_is_id=False):
|
||||
if label is not None:
|
||||
|
@ -33,6 +33,7 @@ from calibre.customize.ui import run_plugins_on_import
|
||||
|
||||
from calibre.utils.filenames import ascii_filename
|
||||
from calibre.utils.date import utcnow, now as nowf, utcfromtimestamp
|
||||
from calibre.utils.ordered_dict import OrderedDict
|
||||
from calibre.ebooks import BOOK_EXTENSIONS, check_ebook_format
|
||||
|
||||
if iswindows:
|
||||
@ -123,22 +124,25 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
if isinstance(self.dbpath, unicode):
|
||||
self.dbpath = self.dbpath.encode(filesystem_encoding)
|
||||
|
||||
self.tag_browser_categories = {
|
||||
'tags' : ['tag', 'name'],
|
||||
'series' : ['series', 'name'],
|
||||
'publishers': ['publisher', 'name'],
|
||||
'authors' : ['author', 'name'],
|
||||
'news' : ['news', 'name'],
|
||||
'ratings' : ['rating', 'rating']
|
||||
}
|
||||
self.tag_browser_datatype = {
|
||||
'tag' : 'textmult',
|
||||
'series' : None,
|
||||
'publisher' : 'text',
|
||||
'author' : 'text',
|
||||
'news' : None,
|
||||
'rating' : 'rating',
|
||||
}
|
||||
# Order as has been customary in the tags pane.
|
||||
self.tag_browser_categories = OrderedDict([
|
||||
('authors', {'table':'authors', 'column':'name', 'type':'text', 'name':_('Authors')}),
|
||||
('series', {'table':'series', 'column':'name', 'type':None, 'name':_('Series')}),
|
||||
('formats', {'table':None, 'column':None, 'type':None, 'name':_('Formats')}),
|
||||
('publishers',{'table':'publishers', 'column':'name', 'type':'text', 'name':_('Publishers')}),
|
||||
('ratings', {'table':'ratings', 'column':'rating', 'type':'rating', 'name':_('Ratings')}),
|
||||
('news', {'table':'news', 'column':'name', 'type':None, 'name':_('News')}),
|
||||
('tags', {'table':'tags', 'column':'name', 'type':'textmult', 'name':_('Tags')}),
|
||||
])
|
||||
|
||||
# self.tag_browser_datatype = {
|
||||
# 'tag' : 'textmult',
|
||||
# 'series' : None,
|
||||
# 'publisher' : 'text',
|
||||
# 'author' : 'text',
|
||||
# 'news' : None,
|
||||
# 'rating' : 'rating',
|
||||
# }
|
||||
|
||||
self.tag_browser_formatters = {'rating': lambda x:u'\u2605'*int(round(x/2.))}
|
||||
|
||||
@ -653,17 +657,22 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
self.books_list_filter.change([] if not ids else ids)
|
||||
|
||||
categories = {}
|
||||
for tn, cn in self.tag_browser_categories.items():
|
||||
for category in self.tag_browser_categories.keys():
|
||||
tn = self.tag_browser_categories[category]['table']
|
||||
categories[category] = [] #reserve the position in the ordered list
|
||||
if tn is None:
|
||||
continue
|
||||
cn = self.tag_browser_categories[category]['column']
|
||||
if ids is None:
|
||||
query = 'SELECT id, {0}, count FROM tag_browser_{1}'.format(cn[1], tn)
|
||||
query = 'SELECT id, {0}, count FROM tag_browser_{1}'.format(cn, tn)
|
||||
else:
|
||||
query = 'SELECT id, {0}, count FROM tag_browser_filtered_{1}'.format(cn[1], tn)
|
||||
query = 'SELECT id, {0}, count FROM tag_browser_filtered_{1}'.format(cn, tn)
|
||||
if sort_on_count:
|
||||
query += ' ORDER BY count DESC'
|
||||
else:
|
||||
query += ' ORDER BY {0} ASC'.format(cn[1])
|
||||
query += ' ORDER BY {0} ASC'.format(cn)
|
||||
data = self.conn.get(query)
|
||||
category = cn[0]
|
||||
# category = cn[0]
|
||||
icon, tooltip = None, ''
|
||||
if icon_map:
|
||||
if category in icon_map:
|
||||
@ -671,14 +680,14 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
else:
|
||||
icon = icon_map['*custom']
|
||||
tooltip = self.custom_column_label_map[category]['name']
|
||||
datatype = self.tag_browser_datatype[category]
|
||||
datatype = self.tag_browser_categories[category]['type']
|
||||
formatter = self.tag_browser_formatters.get(datatype, lambda x: x)
|
||||
categories[category] = [Tag(formatter(r[1]), count=r[2], id=r[0],
|
||||
icon=icon, tooltip = tooltip)
|
||||
for r in data
|
||||
if r[2] > 0 and
|
||||
(datatype != 'rating' or len(formatter(r[1])) > 0)]
|
||||
categories['format'] = []
|
||||
categories['formats'] = []
|
||||
for fmt in self.conn.get('SELECT DISTINCT format FROM data'):
|
||||
fmt = fmt[0]
|
||||
if ids is not None:
|
||||
@ -693,13 +702,13 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
WHERE format="%s"'''%fmt,
|
||||
all=False)
|
||||
if count > 0:
|
||||
categories['format'].append(Tag(fmt, count=count))
|
||||
categories['formats'].append(Tag(fmt, count=count))
|
||||
|
||||
if sort_on_count:
|
||||
categories['format'].sort(cmp=lambda x,y:cmp(x.count, y.count),
|
||||
categories['formats'].sort(cmp=lambda x,y:cmp(x.count, y.count),
|
||||
reverse=True)
|
||||
else:
|
||||
categories['format'].sort(cmp=lambda x,y:cmp(x.name, y.name))
|
||||
categories['formats'].sort(cmp=lambda x,y:cmp(x.name, y.name))
|
||||
return categories
|
||||
|
||||
def tags_older_than(self, tag, delta):
|
||||
|
100
src/calibre/utils/ordered_dict.py
Normal file
100
src/calibre/utils/ordered_dict.py
Normal file
@ -0,0 +1,100 @@
|
||||
from UserDict import DictMixin
|
||||
|
||||
class OrderedDict(dict, DictMixin):
|
||||
|
||||
def __init__(self, *args, **kwds):
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
try:
|
||||
self.__end
|
||||
except AttributeError:
|
||||
self.clear()
|
||||
self.update(*args, **kwds)
|
||||
|
||||
def clear(self):
|
||||
self.__end = end = []
|
||||
end += [None, end, end] # sentinel node for doubly linked list
|
||||
self.__map = {} # key --> [key, prev, next]
|
||||
dict.clear(self)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key not in self:
|
||||
end = self.__end
|
||||
curr = end[1]
|
||||
curr[2] = end[1] = self.__map[key] = [key, curr, end]
|
||||
dict.__setitem__(self, key, value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
dict.__delitem__(self, key)
|
||||
key, prev, next = self.__map.pop(key)
|
||||
prev[2] = next
|
||||
next[1] = prev
|
||||
|
||||
def __iter__(self):
|
||||
end = self.__end
|
||||
curr = end[2]
|
||||
while curr is not end:
|
||||
yield curr[0]
|
||||
curr = curr[2]
|
||||
|
||||
def __reversed__(self):
|
||||
end = self.__end
|
||||
curr = end[1]
|
||||
while curr is not end:
|
||||
yield curr[0]
|
||||
curr = curr[1]
|
||||
|
||||
def popitem(self, last=True):
|
||||
if not self:
|
||||
raise KeyError('dictionary is empty')
|
||||
if last:
|
||||
key = reversed(self).next()
|
||||
else:
|
||||
key = iter(self).next()
|
||||
value = self.pop(key)
|
||||
return key, value
|
||||
|
||||
def __reduce__(self):
|
||||
items = [[k, self[k]] for k in self]
|
||||
tmp = self.__map, self.__end
|
||||
del self.__map, self.__end
|
||||
inst_dict = vars(self).copy()
|
||||
self.__map, self.__end = tmp
|
||||
if inst_dict:
|
||||
return (self.__class__, (items,), inst_dict)
|
||||
return self.__class__, (items,)
|
||||
|
||||
def keys(self):
|
||||
return list(self)
|
||||
|
||||
setdefault = DictMixin.setdefault
|
||||
update = DictMixin.update
|
||||
pop = DictMixin.pop
|
||||
values = DictMixin.values
|
||||
items = DictMixin.items
|
||||
iterkeys = DictMixin.iterkeys
|
||||
itervalues = DictMixin.itervalues
|
||||
iteritems = DictMixin.iteritems
|
||||
|
||||
def __repr__(self):
|
||||
if not self:
|
||||
return '%s()' % (self.__class__.__name__,)
|
||||
return '%s(%r)' % (self.__class__.__name__, self.items())
|
||||
|
||||
def copy(self):
|
||||
return self.__class__(self)
|
||||
|
||||
@classmethod
|
||||
def fromkeys(cls, iterable, value=None):
|
||||
d = cls()
|
||||
for key in iterable:
|
||||
d[key] = value
|
||||
return d
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, OrderedDict):
|
||||
return len(self)==len(other) and self.items() == other.items()
|
||||
return dict.__eq__(self, other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
Loading…
x
Reference in New Issue
Block a user