First pass at converting db2.get_categories to return a complete dict

This commit is contained in:
Charles Haley 2010-05-23 21:34:19 +01:00
parent 4946a2f2ad
commit 3b557de4c7
4 changed files with 141 additions and 32 deletions

View File

@ -199,8 +199,8 @@ class TagsModel(QAbstractItemModel): # {{{
categories_orig = [_('Authors'), _('Series'), _('Formats'), _('Publishers'), categories_orig = [_('Authors'), _('Series'), _('Formats'), _('Publishers'),
_('Ratings'), _('News'), _('Tags')] _('Ratings'), _('News'), _('Tags')]
row_map_orig = ['author', 'series', 'format', 'publisher', 'rating', row_map_orig = ['authors', 'series', 'formats', 'publishers', 'ratings',
'news', 'tag'] 'news', 'tags']
tags_categories_start= 7 tags_categories_start= 7
search_keys=['search', _('Searches')] search_keys=['search', _('Searches')]
@ -264,8 +264,8 @@ class TagsModel(QAbstractItemModel): # {{{
self.cat_icon_map.append(self.cat_icon_map_orig[i]) self.cat_icon_map.append(self.cat_icon_map_orig[i])
# Clean up the author's tags, getting rid of the '|' characters # Clean up the author's tags, getting rid of the '|' characters
if data['author'] is not None: if data['authors'] is not None:
for t in data['author']: for t in data['authors']:
t.name = t.name.replace('|', ',') t.name = t.name.replace('|', ',')
# Now do the user-defined categories. There is a time/space tradeoff here. # Now do the user-defined categories. There is a time/space tradeoff here.

View File

@ -144,8 +144,8 @@ class CustomColumns(object):
for i, v in self.custom_column_num_map.items(): for i, v in self.custom_column_num_map.items():
if v['normalized']: if v['normalized']:
tn = 'custom_column_{0}'.format(i) tn = 'custom_column_{0}'.format(i)
self.tag_browser_categories[tn] = [v['label'], 'value'] self.tag_browser_categories[v['label']] = {'table':tn, 'column':'value', 'type':v['datatype'], 'name':v['name']}
self.tag_browser_datatype[v['label']] = v['datatype'] #self.tag_browser_datatype[v['label']] = v['datatype']
def get_custom(self, idx, label=None, num=None, index_is_id=False): def get_custom(self, idx, label=None, num=None, index_is_id=False):
if label is not None: if label is not None:

View File

@ -33,6 +33,7 @@ from calibre.customize.ui import run_plugins_on_import
from calibre.utils.filenames import ascii_filename from calibre.utils.filenames import ascii_filename
from calibre.utils.date import utcnow, now as nowf, utcfromtimestamp 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 from calibre.ebooks import BOOK_EXTENSIONS, check_ebook_format
if iswindows: if iswindows:
@ -123,22 +124,25 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if isinstance(self.dbpath, unicode): if isinstance(self.dbpath, unicode):
self.dbpath = self.dbpath.encode(filesystem_encoding) self.dbpath = self.dbpath.encode(filesystem_encoding)
self.tag_browser_categories = { # Order as has been customary in the tags pane.
'tags' : ['tag', 'name'], self.tag_browser_categories = OrderedDict([
'series' : ['series', 'name'], ('authors', {'table':'authors', 'column':'name', 'type':'text', 'name':_('Authors')}),
'publishers': ['publisher', 'name'], ('series', {'table':'series', 'column':'name', 'type':None, 'name':_('Series')}),
'authors' : ['author', 'name'], ('formats', {'table':None, 'column':None, 'type':None, 'name':_('Formats')}),
'news' : ['news', 'name'], ('publishers',{'table':'publishers', 'column':'name', 'type':'text', 'name':_('Publishers')}),
'ratings' : ['rating', 'rating'] ('ratings', {'table':'ratings', 'column':'rating', 'type':'rating', 'name':_('Ratings')}),
} ('news', {'table':'news', 'column':'name', 'type':None, 'name':_('News')}),
self.tag_browser_datatype = { ('tags', {'table':'tags', 'column':'name', 'type':'textmult', 'name':_('Tags')}),
'tag' : 'textmult', ])
'series' : None,
'publisher' : 'text', # self.tag_browser_datatype = {
'author' : 'text', # 'tag' : 'textmult',
'news' : None, # 'series' : None,
'rating' : 'rating', # 'publisher' : 'text',
} # 'author' : 'text',
# 'news' : None,
# 'rating' : 'rating',
# }
self.tag_browser_formatters = {'rating': lambda x:u'\u2605'*int(round(x/2.))} 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) self.books_list_filter.change([] if not ids else ids)
categories = {} 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: 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: 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: if sort_on_count:
query += ' ORDER BY count DESC' query += ' ORDER BY count DESC'
else: else:
query += ' ORDER BY {0} ASC'.format(cn[1]) query += ' ORDER BY {0} ASC'.format(cn)
data = self.conn.get(query) data = self.conn.get(query)
category = cn[0] # category = cn[0]
icon, tooltip = None, '' icon, tooltip = None, ''
if icon_map: if icon_map:
if category in icon_map: if category in icon_map:
@ -671,14 +680,14 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
else: else:
icon = icon_map['*custom'] icon = icon_map['*custom']
tooltip = self.custom_column_label_map[category]['name'] 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) formatter = self.tag_browser_formatters.get(datatype, lambda x: x)
categories[category] = [Tag(formatter(r[1]), count=r[2], id=r[0], categories[category] = [Tag(formatter(r[1]), count=r[2], id=r[0],
icon=icon, tooltip = tooltip) icon=icon, tooltip = tooltip)
for r in data for r in data
if r[2] > 0 and if r[2] > 0 and
(datatype != 'rating' or len(formatter(r[1])) > 0)] (datatype != 'rating' or len(formatter(r[1])) > 0)]
categories['format'] = [] categories['formats'] = []
for fmt in self.conn.get('SELECT DISTINCT format FROM data'): for fmt in self.conn.get('SELECT DISTINCT format FROM data'):
fmt = fmt[0] fmt = fmt[0]
if ids is not None: if ids is not None:
@ -693,13 +702,13 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
WHERE format="%s"'''%fmt, WHERE format="%s"'''%fmt,
all=False) all=False)
if count > 0: if count > 0:
categories['format'].append(Tag(fmt, count=count)) categories['formats'].append(Tag(fmt, count=count))
if sort_on_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) reverse=True)
else: 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 return categories
def tags_older_than(self, tag, delta): def tags_older_than(self, tag, delta):

View 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