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:
|
if self.tag.count == 0:
|
||||||
return QVariant('%s'%(self.tag.name))
|
return QVariant('%s'%(self.tag.name))
|
||||||
else:
|
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:
|
if role == Qt.EditRole:
|
||||||
return QVariant(self.tag.name)
|
return QVariant(self.tag.name)
|
||||||
if role == Qt.DecorationRole:
|
if role == Qt.DecorationRole:
|
||||||
@ -332,6 +335,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
':custom' : QIcon(I('column.svg')),
|
':custom' : QIcon(I('column.svg')),
|
||||||
':user' : QIcon(I('drawer.svg')),
|
':user' : QIcon(I('drawer.svg')),
|
||||||
'search' : QIcon(I('search.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.icon_state_map = [None, QIcon(I('plus.svg')), QIcon(I('minus.svg'))]
|
||||||
self.db = db
|
self.db = db
|
||||||
@ -354,7 +358,14 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
data=self.categories[i],
|
data=self.categories[i],
|
||||||
category_icon=self.category_icon_map[r],
|
category_icon=self.category_icon_map[r],
|
||||||
tooltip=tt, category_key=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]:
|
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)
|
TagTreeItem(parent=c, data=tag, icon_map=self.icon_state_map)
|
||||||
|
|
||||||
def set_search_restriction(self, s):
|
def set_search_restriction(self, s):
|
||||||
@ -417,6 +428,10 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
if len(data[r]) > 0:
|
if len(data[r]) > 0:
|
||||||
self.beginInsertRows(category_index, 0, len(data[r])-1)
|
self.beginInsertRows(category_index, 0, len(data[r])-1)
|
||||||
for tag in data[r]:
|
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)
|
tag.state = state_map.get(tag.name, 0)
|
||||||
t = TagTreeItem(parent=category, data=tag, icon_map=self.icon_state_map)
|
t = TagTreeItem(parent=category, data=tag, icon_map=self.icon_state_map)
|
||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
|
@ -461,14 +461,27 @@ class CustomColumns(object):
|
|||||||
CREATE VIEW tag_browser_{table} AS SELECT
|
CREATE VIEW tag_browser_{table} AS SELECT
|
||||||
id,
|
id,
|
||||||
value,
|
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};
|
FROM {table};
|
||||||
|
|
||||||
CREATE VIEW tag_browser_filtered_{table} AS SELECT
|
CREATE VIEW tag_browser_filtered_{table} AS SELECT
|
||||||
id,
|
id,
|
||||||
value,
|
value,
|
||||||
(SELECT COUNT({lt}.id) FROM {lt} WHERE value={table}.id AND
|
(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};
|
FROM {table};
|
||||||
|
|
||||||
'''.format(lt=lt, table=table),
|
'''.format(lt=lt, table=table),
|
||||||
@ -505,7 +518,7 @@ class CustomColumns(object):
|
|||||||
END;
|
END;
|
||||||
'''.format(table=table),
|
'''.format(table=table),
|
||||||
]
|
]
|
||||||
|
print lines
|
||||||
script = ' \n'.join(lines)
|
script = ' \n'.join(lines)
|
||||||
self.conn.executescript(script)
|
self.conn.executescript(script)
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
@ -56,11 +56,12 @@ copyfile = os.link if hasattr(os, 'link') else shutil.copyfile
|
|||||||
|
|
||||||
class Tag(object):
|
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.name = name
|
||||||
self.id = id
|
self.id = id
|
||||||
self.count = count
|
self.count = count
|
||||||
self.state = state
|
self.state = state
|
||||||
|
self.avg = avg/2 if avg is not None else 0
|
||||||
self.tooltip = tooltip
|
self.tooltip = tooltip
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
|
|
||||||
@ -125,15 +126,16 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
self.connect()
|
self.connect()
|
||||||
self.is_case_sensitive = not iswindows and not isosx and \
|
self.is_case_sensitive = not iswindows and not isosx and \
|
||||||
not os.path.exists(self.dbpath.replace('metadata.db', 'MeTAdAtA.dB'))
|
not os.path.exists(self.dbpath.replace('metadata.db', 'MeTAdAtA.dB'))
|
||||||
SchemaUpgrade.__init__(self)
|
|
||||||
self.initialize_dynamic()
|
self.initialize_dynamic()
|
||||||
|
SchemaUpgrade.__init__(self)
|
||||||
|
|
||||||
def initialize_dynamic(self):
|
def initialize_dynamic(self):
|
||||||
self.conn.executescript(u'''
|
self.conn.executescript(u'''
|
||||||
CREATE TEMP VIEW IF NOT EXISTS tag_browser_news AS SELECT DISTINCT
|
CREATE TEMP VIEW IF NOT EXISTS tag_browser_news AS SELECT DISTINCT
|
||||||
id,
|
id,
|
||||||
name,
|
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
|
FROM tags as x WHERE name!="{0}" AND id IN
|
||||||
(SELECT DISTINCT tag FROM books_tags_link WHERE book IN
|
(SELECT DISTINCT tag FROM books_tags_link WHERE book IN
|
||||||
(SELECT DISTINCT book FROM books_tags_link WHERE tag 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
|
CREATE TEMP VIEW IF NOT EXISTS tag_browser_filtered_news AS SELECT DISTINCT
|
||||||
id,
|
id,
|
||||||
name,
|
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
|
FROM tags as x WHERE name!="{0}" AND id IN
|
||||||
(SELECT DISTINCT tag FROM books_tags_link WHERE book IN
|
(SELECT DISTINCT tag FROM books_tags_link WHERE book IN
|
||||||
(SELECT DISTINCT book FROM books_tags_link WHERE tag IN
|
(SELECT DISTINCT book FROM books_tags_link WHERE tag IN
|
||||||
@ -698,9 +701,9 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
continue
|
continue
|
||||||
cn = cat['column']
|
cn = cat['column']
|
||||||
if ids is None:
|
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:
|
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:
|
if sort_on_count:
|
||||||
query += ' ORDER BY count DESC'
|
query += ' ORDER BY count DESC'
|
||||||
else:
|
else:
|
||||||
@ -733,7 +736,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
formatter = (lambda x:unicode(x))
|
formatter = (lambda x:unicode(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)
|
avg=r[3], icon=icon, tooltip=tooltip)
|
||||||
for r in data if item_not_zero_func(r)]
|
for r in data if item_not_zero_func(r)]
|
||||||
if category == 'series' and not sort_on_count:
|
if category == 'series' and not sort_on_count:
|
||||||
if tweaks['title_series_sorting'] == 'library_order':
|
if tweaks['title_series_sorting'] == 'library_order':
|
||||||
|
@ -292,3 +292,76 @@ class SchemaUpgrade(object):
|
|||||||
for field in self.field_metadata.itervalues():
|
for field in self.field_metadata.itervalues():
|
||||||
if field['is_category'] and not field['is_custom'] and 'link_column' in field:
|
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'])
|
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