mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Prototype implementation of average ratings
This commit is contained in:
parent
1dafae3c4a
commit
de36d8acc9
@ -298,7 +298,10 @@ class TagTreeItem(object): # {{{
|
||||
if self.tag.count == 0:
|
||||
return QVariant('%s'%(self.tag.name))
|
||||
else:
|
||||
return QVariant('[%d] %s'%(self.tag.count, self.tag.name))
|
||||
if self.tag.avg is None:
|
||||
return QVariant('[%d] %s'%(self.tag.count, self.tag.name))
|
||||
else:
|
||||
return QVariant('[%d][%d] %s'%(self.tag.count, self.tag.avg, self.tag.name))
|
||||
if role == Qt.EditRole:
|
||||
return QVariant(self.tag.name)
|
||||
if role == Qt.DecorationRole:
|
||||
@ -332,6 +335,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
':custom' : QIcon(I('column.svg')),
|
||||
':user' : QIcon(I('drawer.svg')),
|
||||
'search' : QIcon(I('search.svg'))})
|
||||
self.categories_with_ratings = ['authors', 'series', 'publisher', 'tags']
|
||||
|
||||
self.icon_state_map = [None, QIcon(I('plus.svg')), QIcon(I('minus.svg'))]
|
||||
self.db = db
|
||||
@ -354,7 +358,14 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
data=self.categories[i],
|
||||
category_icon=self.category_icon_map[r],
|
||||
tooltip=tt, category_key=r)
|
||||
# This duplicates code in refresh(). Having it here as well
|
||||
# can save seconds during startup, because we avoid a second
|
||||
# call to get_node_tree.
|
||||
for tag in data[r]:
|
||||
if r not in self.categories_with_ratings and \
|
||||
not self.db.field_metadata[r]['is_custom'] and \
|
||||
not self.db.field_metadata[r]['kind'] == 'user':
|
||||
tag.avg = None
|
||||
TagTreeItem(parent=c, data=tag, icon_map=self.icon_state_map)
|
||||
|
||||
def set_search_restriction(self, s):
|
||||
@ -417,6 +428,10 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
if len(data[r]) > 0:
|
||||
self.beginInsertRows(category_index, 0, len(data[r])-1)
|
||||
for tag in data[r]:
|
||||
if r not in self.categories_with_ratings and \
|
||||
not self.db.field_metadata[r]['is_custom'] and \
|
||||
not self.db.field_metadata[r]['kind'] == 'user':
|
||||
tag.avg = None
|
||||
tag.state = state_map.get(tag.name, 0)
|
||||
t = TagTreeItem(parent=category, data=tag, icon_map=self.icon_state_map)
|
||||
self.endInsertRows()
|
||||
|
@ -461,14 +461,27 @@ class CustomColumns(object):
|
||||
CREATE VIEW tag_browser_{table} AS SELECT
|
||||
id,
|
||||
value,
|
||||
(SELECT COUNT(id) FROM {lt} WHERE value={table}.id) count
|
||||
(SELECT COUNT(id) FROM {lt} WHERE value={table}.id) count,
|
||||
(SELECT AVG(r.rating)
|
||||
FROM {lt},
|
||||
books_ratings_link as bl,
|
||||
ratings as r
|
||||
WHERE {lt}.value={table}.id and bl.book={lt}.book and
|
||||
r.id = bl.rating and r.rating <> 0) avg_rating
|
||||
FROM {table};
|
||||
|
||||
CREATE VIEW tag_browser_filtered_{table} AS SELECT
|
||||
id,
|
||||
value,
|
||||
(SELECT COUNT({lt}.id) FROM {lt} WHERE value={table}.id AND
|
||||
books_list_filter(book)) count
|
||||
books_list_filter(book)) count,
|
||||
(SELECT AVG(r.rating)
|
||||
FROM {lt},
|
||||
books_ratings_link as bl,
|
||||
ratings as r
|
||||
WHERE {lt}.value={table}.id AND bl.book={lt}.book AND
|
||||
r.id = bl.rating AND r.rating <> 0 AND
|
||||
books_list_filter(bl.book)) avg_rating
|
||||
FROM {table};
|
||||
|
||||
'''.format(lt=lt, table=table),
|
||||
@ -505,7 +518,7 @@ class CustomColumns(object):
|
||||
END;
|
||||
'''.format(table=table),
|
||||
]
|
||||
|
||||
print lines
|
||||
script = ' \n'.join(lines)
|
||||
self.conn.executescript(script)
|
||||
self.conn.commit()
|
||||
|
@ -56,11 +56,12 @@ copyfile = os.link if hasattr(os, 'link') else shutil.copyfile
|
||||
|
||||
class Tag(object):
|
||||
|
||||
def __init__(self, name, id=None, count=0, state=0, tooltip=None, icon=None):
|
||||
def __init__(self, name, id=None, count=0, state=0, avg=0, tooltip=None, icon=None):
|
||||
self.name = name
|
||||
self.id = id
|
||||
self.count = count
|
||||
self.state = state
|
||||
self.avg = avg/2 if avg is not None else 0
|
||||
self.tooltip = tooltip
|
||||
self.icon = icon
|
||||
|
||||
@ -125,15 +126,16 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
self.connect()
|
||||
self.is_case_sensitive = not iswindows and not isosx and \
|
||||
not os.path.exists(self.dbpath.replace('metadata.db', 'MeTAdAtA.dB'))
|
||||
SchemaUpgrade.__init__(self)
|
||||
self.initialize_dynamic()
|
||||
SchemaUpgrade.__init__(self)
|
||||
|
||||
def initialize_dynamic(self):
|
||||
self.conn.executescript(u'''
|
||||
CREATE TEMP VIEW IF NOT EXISTS tag_browser_news AS SELECT DISTINCT
|
||||
id,
|
||||
name,
|
||||
(SELECT COUNT(books_tags_link.id) FROM books_tags_link WHERE tag=x.id) count
|
||||
(SELECT COUNT(books_tags_link.id) FROM books_tags_link WHERE tag=x.id) count,
|
||||
(0) as avg_rating
|
||||
FROM tags as x WHERE name!="{0}" AND id IN
|
||||
(SELECT DISTINCT tag FROM books_tags_link WHERE book IN
|
||||
(SELECT DISTINCT book FROM books_tags_link WHERE tag IN
|
||||
@ -144,7 +146,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
CREATE TEMP VIEW IF NOT EXISTS tag_browser_filtered_news AS SELECT DISTINCT
|
||||
id,
|
||||
name,
|
||||
(SELECT COUNT(books_tags_link.id) FROM books_tags_link WHERE tag=x.id and books_list_filter(book)) count
|
||||
(SELECT COUNT(books_tags_link.id) FROM books_tags_link WHERE tag=x.id and books_list_filter(book)) count,
|
||||
(0) as avg_rating
|
||||
FROM tags as x WHERE name!="{0}" AND id IN
|
||||
(SELECT DISTINCT tag FROM books_tags_link WHERE book IN
|
||||
(SELECT DISTINCT book FROM books_tags_link WHERE tag IN
|
||||
@ -698,9 +701,9 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
continue
|
||||
cn = cat['column']
|
||||
if ids is None:
|
||||
query = 'SELECT id, {0}, count FROM tag_browser_{1}'.format(cn, tn)
|
||||
query = 'SELECT id, {0}, count, avg_rating FROM tag_browser_{1}'.format(cn, tn)
|
||||
else:
|
||||
query = 'SELECT id, {0}, count FROM tag_browser_filtered_{1}'.format(cn, tn)
|
||||
query = 'SELECT id, {0}, count, avg_rating FROM tag_browser_filtered_{1}'.format(cn, tn)
|
||||
if sort_on_count:
|
||||
query += ' ORDER BY count DESC'
|
||||
else:
|
||||
@ -733,7 +736,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
formatter = (lambda x:unicode(x))
|
||||
|
||||
categories[category] = [Tag(formatter(r[1]), count=r[2], id=r[0],
|
||||
icon=icon, tooltip = tooltip)
|
||||
avg=r[3], icon=icon, tooltip=tooltip)
|
||||
for r in data if item_not_zero_func(r)]
|
||||
if category == 'series' and not sort_on_count:
|
||||
if tweaks['title_series_sorting'] == 'library_order':
|
||||
|
@ -292,3 +292,76 @@ class SchemaUpgrade(object):
|
||||
for field in self.field_metadata.itervalues():
|
||||
if field['is_category'] and not field['is_custom'] and 'link_column' in field:
|
||||
create_tag_browser_view(field['table'], field['link_column'], field['column'])
|
||||
|
||||
def upgrade_version_11(self):
|
||||
'Add average rating to tag browser views'
|
||||
def create_std_tag_browser_view(table_name, column_name, view_column_name):
|
||||
script = ('''
|
||||
DROP VIEW IF EXISTS tag_browser_{tn};
|
||||
CREATE VIEW tag_browser_{tn} AS SELECT
|
||||
id,
|
||||
{vcn},
|
||||
(SELECT COUNT(id) FROM books_{tn}_link WHERE {cn}={tn}.id) count,
|
||||
(SELECT AVG(ratings.rating)
|
||||
FROM books_{tn}_link as tl, books_ratings_link as bl, ratings
|
||||
WHERE tl.{cn}={tn}.id and bl.book=tl.book and
|
||||
ratings.id = bl.rating and ratings.rating <> 0) avg_rating
|
||||
FROM {tn};
|
||||
DROP VIEW IF EXISTS tag_browser_filtered_{tn};
|
||||
CREATE VIEW tag_browser_filtered_{tn} AS SELECT
|
||||
id,
|
||||
{vcn},
|
||||
(SELECT COUNT(books_{tn}_link.id) FROM books_{tn}_link WHERE
|
||||
{cn}={tn}.id AND books_list_filter(book)) count,
|
||||
(SELECT AVG(ratings.rating)
|
||||
FROM books_{tn}_link as tl, books_ratings_link as bl, ratings
|
||||
WHERE tl.{cn}={tn}.id and bl.book=tl.book and
|
||||
ratings.id = bl.rating and ratings.rating <> 0 AND
|
||||
books_list_filter(bl.book)) avg_rating
|
||||
FROM {tn};
|
||||
|
||||
'''.format(tn=table_name, cn=column_name, vcn=view_column_name))
|
||||
self.conn.executescript(script)
|
||||
|
||||
def create_cust_tag_browser_view(table_name, link_table_name):
|
||||
script = '''
|
||||
DROP VIEW IF EXISTS tag_browser_{table};
|
||||
CREATE VIEW tag_browser_{table} AS SELECT
|
||||
id,
|
||||
value,
|
||||
(SELECT COUNT(id) FROM {lt} WHERE value={table}.id) count,
|
||||
(SELECT AVG(r.rating)
|
||||
FROM {lt},
|
||||
books_ratings_link as bl,
|
||||
ratings as r
|
||||
WHERE {lt}.value={table}.id and bl.book={lt}.book and
|
||||
r.id = bl.rating and r.rating <> 0) avg_rating
|
||||
FROM {table};
|
||||
|
||||
DROP VIEW IF EXISTS tag_browser_filtered_{table};
|
||||
CREATE VIEW tag_browser_filtered_{table} AS SELECT
|
||||
id,
|
||||
value,
|
||||
(SELECT COUNT({lt}.id) FROM {lt} WHERE value={table}.id AND
|
||||
books_list_filter(book)) count,
|
||||
(SELECT AVG(r.rating)
|
||||
FROM {lt},
|
||||
books_ratings_link as bl,
|
||||
ratings as r
|
||||
WHERE {lt}.value={table}.id AND bl.book={lt}.book AND
|
||||
r.id = bl.rating AND r.rating <> 0 AND
|
||||
books_list_filter(bl.book)) avg_rating
|
||||
FROM {table};
|
||||
'''.format(lt=link_table_name, table=table_name)
|
||||
self.conn.executescript(script)
|
||||
|
||||
for field in self.field_metadata.itervalues():
|
||||
if field['is_category'] and not field['is_custom'] and 'link_column' in field:
|
||||
create_std_tag_browser_view(field['table'], field['link_column'],
|
||||
field['column'])
|
||||
|
||||
for field in self.field_metadata.itervalues():
|
||||
if field['is_category'] and field['is_custom']:
|
||||
link_table_name = 'books_custom_column_%d_link'%field['colnum']
|
||||
print 'try to upgrade cust col', field['table'], link_table_name
|
||||
create_cust_tag_browser_view(field['table'], link_table_name)
|
||||
|
Loading…
x
Reference in New Issue
Block a user