Tag browser: Always show the book counts on the right edge of the Tag Browser

This commit is contained in:
Kovid Goyal 2016-09-05 10:28:00 +05:30
parent a28efc879f
commit 31f109df7e
2 changed files with 71 additions and 36 deletions

View File

@ -27,6 +27,7 @@ from calibre.utils.formatter import EvalFormatter
TAG_SEARCH_STATES = {'clear': 0, 'mark_plus': 1, 'mark_plusplus': 2, TAG_SEARCH_STATES = {'clear': 0, 'mark_plus': 1, 'mark_plusplus': 2,
'mark_minus': 3, 'mark_minusminus': 4} 'mark_minus': 3, 'mark_minusminus': 4}
DRAG_IMAGE_ROLE = Qt.UserRole + 1000 DRAG_IMAGE_ROLE = Qt.UserRole + 1000
COUNT_ROLE = DRAG_IMAGE_ROLE + 1
_bf = None _bf = None
def bf(): def bf():
@ -152,7 +153,7 @@ class TagTreeItem(object): # {{{
def category_data(self, role): def category_data(self, role):
if role == Qt.DisplayRole: if role == Qt.DisplayRole:
return (self.py_name + ' [%d]'%len(self.child_tags())) return self.py_name
if role == Qt.EditRole: if role == Qt.EditRole:
return (self.py_name) return (self.py_name)
if role == Qt.DecorationRole: if role == Qt.DecorationRole:
@ -166,6 +167,8 @@ class TagTreeItem(object): # {{{
if role == DRAG_IMAGE_ROLE: if role == DRAG_IMAGE_ROLE:
self.ensure_icon() self.ensure_icon()
return self.icon_state_map[0] return self.icon_state_map[0]
if role == COUNT_ROLE:
return len(self.child_tags())
return None return None
def tag_data(self, role): def tag_data(self, role):
@ -178,11 +181,7 @@ class TagTreeItem(object): # {{{
else: else:
name = tag.name name = tag.name
if role == Qt.DisplayRole: if role == Qt.DisplayRole:
count = self.item_count return unicode(name)
if count == 0:
return ('%s'%(name))
else:
return ('[%d] %s'%(count, name))
if role == Qt.EditRole: if role == Qt.EditRole:
return (tag.original_name) return (tag.original_name)
if role == Qt.DecorationRole: if role == Qt.DecorationRole:
@ -202,10 +201,14 @@ class TagTreeItem(object): # {{{
tt.append(_('Books in this category are unrated')) tt.append(_('Books in this category are unrated'))
if self.type == self.TAG and self.tag.category == 'search': if self.type == self.TAG and self.tag.category == 'search':
tt.append(_('Search expression:') + ' ' + self.tag.search_expression) tt.append(_('Search expression:') + ' ' + self.tag.search_expression)
if self.type == self.TAG:
tt.append(_('Number of books: %s') % self.item_count)
return '\n'.join(tt) return '\n'.join(tt)
if role == DRAG_IMAGE_ROLE: if role == DRAG_IMAGE_ROLE:
self.ensure_icon() self.ensure_icon()
return self.icon_state_map[0] return self.icon_state_map[0]
if role == COUNT_ROLE:
return self.item_count
return None return None
def dump_data(self): def dump_data(self):

View File

@ -11,14 +11,16 @@ import cPickle, os
from functools import partial from functools import partial
from itertools import izip from itertools import izip
from PyQt5.Qt import (QStyledItemDelegate, Qt, QTreeView, pyqtSignal, QSize, from PyQt5.Qt import (
QIcon, QApplication, QMenu, QPoint, QModelIndex, QToolTip, QCursor, QStyledItemDelegate, Qt, QTreeView, pyqtSignal, QSize, QIcon, QApplication,
QDrag) QMenu, QPoint, QModelIndex, QToolTip, QCursor, QDrag, QRect,
QLinearGradient, QPalette, QColor, QPen, QBrush
)
from calibre import sanitize_file_name_unicode from calibre import sanitize_file_name_unicode
from calibre.constants import config_dir from calibre.constants import config_dir
from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES, from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES,
TagsModel, DRAG_IMAGE_ROLE) TagsModel, DRAG_IMAGE_ROLE, COUNT_ROLE)
from calibre.gui2 import config, gprefs, choose_files, pixmap_to_data from calibre.gui2 import config, gprefs, choose_files, pixmap_to_data
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
@ -28,43 +30,73 @@ class TagDelegate(QStyledItemDelegate): # {{{
QStyledItemDelegate.__init__(self, *args, **kwargs) QStyledItemDelegate.__init__(self, *args, **kwargs)
self.old_look = gprefs['tag_browser_old_look'] self.old_look = gprefs['tag_browser_old_look']
def draw_average_rating(self, item, style, painter, option, widget):
rating = item.average_rating
if rating is None:
return
r = style.subElementRect(style.SE_ItemViewItemDecoration, option, widget)
icon = option.icon
painter.save()
nr = r.adjusted(0, 0, 0, 0)
nr.setBottom(r.bottom()-int(r.height()*(rating/5.0)))
painter.setClipRect(nr)
bg = option.palette.window()
if self.old_look:
bg = option.palette.alternateBase() if option.features&option.Alternate else option.palette.base()
painter.fillRect(r, bg)
style.proxy().drawPrimitive(style.PE_PanelItemViewItem, option, painter, widget)
painter.setOpacity(0.3)
icon.paint(painter, r, option.decorationAlignment, icon.Normal, icon.On)
painter.restore()
def draw_icon(self, style, painter, option, widget):
r = style.subElementRect(style.SE_ItemViewItemDecoration, option, widget)
icon = option.icon
icon.paint(painter, r, option.decorationAlignment, icon.Normal, icon.On)
def draw_text(self, style, painter, option, widget, index, item):
tr = style.subElementRect(style.SE_ItemViewItemText, option, widget)
count = unicode(index.data(COUNT_ROLE))
width = painter.fontMetrics().boundingRect(count).width()
r = QRect(tr)
r.setRight(r.right() - 1)
r.setLeft(r.right() - width - 4)
painter.drawText(r, Qt.AlignCenter | Qt.TextSingleLine, count)
tr.setRight(r.left() - 1)
flags = Qt.AlignVCenter | Qt.AlignLeft | Qt.TextSingleLine
text = index.data(Qt.DisplayRole)
lr = QRect(tr)
lr.setRight(lr.right() * 2)
br = painter.boundingRect(lr, flags, text)
if br.width() > tr.width():
g = QLinearGradient(tr.topLeft(), tr.topRight())
c = option.palette.color(QPalette.WindowText)
g.setColorAt(0, c), g.setColorAt(0.8, c)
c = QColor(c)
c.setAlpha(0)
g.setColorAt(1, c)
pen = QPen()
pen.setBrush(QBrush(g))
painter.setPen(pen)
painter.drawText(tr, flags, text)
def paint(self, painter, option, index): def paint(self, painter, option, index):
item = index.data(Qt.UserRole) item = index.data(Qt.UserRole)
QStyledItemDelegate.paint(self, painter, option, index) QStyledItemDelegate.paint(self, painter, option, QModelIndex())
widget = self.parent() widget = self.parent()
style = QApplication.style() if widget is None else widget.style() style = QApplication.style() if widget is None else widget.style()
self.initStyleOption(option, index) self.initStyleOption(option, index)
self.draw_icon(style, painter, option, widget)
self.draw_text(style, painter, option, widget, index, item)
if item.boxed: if item.boxed:
r = style.subElementRect(style.SE_ItemViewItemFocusRect, option, r = style.subElementRect(style.SE_ItemViewItemFocusRect, option,
widget) widget)
painter.save()
painter.drawLine(r.bottomLeft(), r.bottomRight()) painter.drawLine(r.bottomLeft(), r.bottomRight())
painter.restore()
if item.type != TagTreeItem.TAG: if item.type != TagTreeItem.TAG:
return return
if item.tag.state == 0 and config['show_avg_rating']: if item.tag.state == 0:
rating = item.average_rating if config['show_avg_rating']:
if rating is None: self.draw_average_rating(item, style, painter, option, widget)
return
r = style.subElementRect(style.SE_ItemViewItemDecoration,
option, widget)
icon = option.icon
painter.save()
nr = r.adjusted(0, 0, 0, 0)
nr.setBottom(r.bottom()-int(r.height()*(rating/5.0)))
painter.setClipRect(nr)
bg = option.palette.window()
if self.old_look:
bg = (option.palette.alternateBase() if
option.features&option.Alternate else
option.palette.base())
painter.fillRect(r, bg)
style.proxy().drawPrimitive(style.PE_PanelItemViewItem, option,
painter, widget)
painter.setOpacity(0.3)
icon.paint(painter, r, option.decorationAlignment, icon.Normal,
icon.On)
painter.restore()
# }}} # }}}