diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py
index 58b78cc00a..c976c3428f 100644
--- a/src/calibre/gui2/__init__.py
+++ b/src/calibre/gui2/__init__.py
@@ -37,6 +37,8 @@ def _config():
help=_('Notify when a new version is available'))
c.add_opt('use_roman_numerals_for_series_number', default=True,
help=_('Use Roman numerals for series number'))
+ c.add_opt('sort_by_popularity', default=False,
+ help=_('Sort tags list by popularity'))
c.add_opt('cover_flow_queue_length', default=6,
help=_('Number of covers to show in the cover browsing mode'))
c.add_opt('LRF_conversion_defaults', default=[],
diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py
index c698b16286..31f6b891a7 100644
--- a/src/calibre/gui2/main.py
+++ b/src/calibre/gui2/main.py
@@ -250,7 +250,8 @@ class Main(MainWindow, Ui_MainWindow):
self.tags_view.setVisible(False)
self.match_all.setVisible(False)
self.match_any.setVisible(False)
- self.tags_view.set_database(db, self.match_all)
+ self.popularity.setVisible(False)
+ self.tags_view.set_database(db, self.match_all, self.popularity)
self.connect(self.tags_view, SIGNAL('tags_marked(PyQt_PyObject, PyQt_PyObject)'),
self.search.search_from_tokens)
self.connect(self.status_bar.tag_view_button, SIGNAL('toggled(bool)'), self.toggle_tags_view)
@@ -300,11 +301,13 @@ class Main(MainWindow, Ui_MainWindow):
self.tags_view.setVisible(True)
self.match_all.setVisible(True)
self.match_any.setVisible(True)
+ self.popularity.setVisible(True)
self.tags_view.setFocus(Qt.OtherFocusReason)
else:
self.tags_view.setVisible(False)
self.match_all.setVisible(False)
self.match_any.setVisible(False)
+ self.popularity.setVisible(False)
def sync_cf_to_listview(self, index, *args):
if not hasattr(index, 'row') and self.library_view.currentIndex().row() != index:
diff --git a/src/calibre/gui2/main.ui b/src/calibre/gui2/main.ui
index 59ce80884a..065b322b04 100644
--- a/src/calibre/gui2/main.ui
+++ b/src/calibre/gui2/main.ui
@@ -262,6 +262,13 @@
+ -
+
+
+ Sort by &popularity
+
+
+
-
diff --git a/src/calibre/gui2/tags.py b/src/calibre/gui2/tags.py
index 2dba15b95d..dd8b3e076b 100644
--- a/src/calibre/gui2/tags.py
+++ b/src/calibre/gui2/tags.py
@@ -8,7 +8,7 @@ Browsing book collection by tags.
'''
from PyQt4.Qt import QAbstractItemModel, Qt, QVariant, QTreeView, QModelIndex, \
QFont, SIGNAL, QSize, QColor, QIcon
-
+from calibre.gui2 import config
NONE = QVariant()
class TagsView(QTreeView):
@@ -19,23 +19,24 @@ class TagsView(QTreeView):
self.setCursor(Qt.PointingHandCursor)
self.setIconSize(QSize(30, 30))
- def set_database(self, db, match_all):
+ def set_database(self, db, match_all, popularity):
self._model = TagsModel(db)
+ self.popularity = popularity
self.match_all = match_all
self.setModel(self._model)
self.connect(self, SIGNAL('clicked(QModelIndex)'), self.toggle)
+ self.popularity.setChecked(config['sort_by_popularity'])
+ self.connect(self.popularity, SIGNAL('stateChanged(int)'), self.sort_changed)
+
+ def sort_changed(self, state):
+ config.set('sort_by_popularity', state == Qt.Checked)
+ self.model().refresh()
def toggle(self, index):
if self._model.toggle(index):
self.emit(SIGNAL('tags_marked(PyQt_PyObject, PyQt_PyObject)'),
self._model.tokens(), self.match_all.isChecked())
-class Tag(unicode):
-
- def __init__(self, name):
- unicode.__init__(self, name)
- self.state = 0
-
class TagsModel(QAbstractItemModel):
categories = [_('Authors'), _('Series'), _('Formats'), _('Publishers'), _('Tags')]
@@ -61,9 +62,9 @@ class TagsModel(QAbstractItemModel):
def refresh(self):
old_data = self._data
- self._data = self.db.get_categories()
+ self._data = self.db.get_categories(config['sort_by_popularity'])
for key in self._data:
- self._data[key] = list(map(Tag, self._data[key]))
+ self._data[key] = self._data[key]
for key in old_data.keys():
for tag in old_data[key]:
try:
@@ -152,7 +153,7 @@ class TagsModel(QAbstractItemModel):
def tag_data(self, index, role):
category = self.row_map[index.parent().row()]
if role == Qt.DisplayRole:
- return QVariant(self._data[category][index.row()])
+ return QVariant(self._data[category][index.row()].as_string())
if role == Qt.DecorationRole:
return self.status_map[self._data[category][index.row()].state]
return NONE
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index a5b0c83a41..b8ad998b3a 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -326,6 +326,16 @@ class ResultCache(object):
ans = (no_tags + ans) if order == 'ASC' else (ans + no_tags)
return ans
+class Tag(unicode):
+
+ def __init__(self, name):
+ unicode.__init__(self, name)
+ self.count = 0
+ self.state = 0
+
+ def as_string(self):
+ return u'[%d] %s'%(self.count, self)
+
class LibraryDatabase2(LibraryDatabase):
'''
An ebook metadata database that stores references to ebook files on disk.
@@ -683,7 +693,7 @@ class LibraryDatabase2(LibraryDatabase):
self.conn.execute(st%dict(ltable='series', table='series', ltable_col='series'))
self.conn.commit()
- def get_categories(self):
+ def get_categories(self, sort_on_count=False):
categories = {}
def get(name, category, field='name'):
ans = self.conn.execute('SELECT DISTINCT %s FROM %s'%(field, name)).fetchall()
@@ -691,9 +701,23 @@ class LibraryDatabase2(LibraryDatabase):
try:
ans.remove('')
except ValueError: pass
- ans.sort()
- categories[category] = ans
- for x in (('authors', 'author'), ('tags', 'tag'), ('publishers', 'publisher'), ('series', 'series')):
+ categories[category] = list(map(Tag, ans))
+ tags = categories[category]
+ if name != 'data':
+ for tag in tags:
+ id = self.conn.execute('SELECT id FROM %s WHERE %s=?'%(name, field), (tag,)).fetchone()
+ if id:
+ id = id[0]
+ tag.id = id
+ for tag in tags:
+ if tag.id is not None:
+ tag.count = self.conn.execute('SELECT COUNT(id) FROM books_%s_link WHERE %s=?'%(name, category), (tag.id,)).fetchone()[0]
+ else:
+ for tag in tags:
+ tag.count = self.conn.execute('SELECT COUNT(format) FROM data WHERE format=?', (tag,)).fetchone()[0]
+ tags.sort(reverse=sort_on_count, cmp=(lambda x,y:cmp(x.count,y.count)) if sort_on_count else cmp)
+ for x in (('authors', 'author'), ('tags', 'tag'), ('publishers', 'publisher'),
+ ('series', 'series')):
get(*x)
get('data', 'format', 'format')
return categories