From 31f109df7e37df034f4a02cb13474f475d6bcfaf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 5 Sep 2016 10:28:00 +0530 Subject: [PATCH] Tag browser: Always show the book counts on the right edge of the Tag Browser --- src/calibre/gui2/tag_browser/model.py | 15 +++-- src/calibre/gui2/tag_browser/view.py | 92 ++++++++++++++++++--------- 2 files changed, 71 insertions(+), 36 deletions(-) diff --git a/src/calibre/gui2/tag_browser/model.py b/src/calibre/gui2/tag_browser/model.py index e613a88ed3..478d8177c4 100644 --- a/src/calibre/gui2/tag_browser/model.py +++ b/src/calibre/gui2/tag_browser/model.py @@ -27,6 +27,7 @@ from calibre.utils.formatter import EvalFormatter TAG_SEARCH_STATES = {'clear': 0, 'mark_plus': 1, 'mark_plusplus': 2, 'mark_minus': 3, 'mark_minusminus': 4} DRAG_IMAGE_ROLE = Qt.UserRole + 1000 +COUNT_ROLE = DRAG_IMAGE_ROLE + 1 _bf = None def bf(): @@ -152,7 +153,7 @@ class TagTreeItem(object): # {{{ def category_data(self, role): if role == Qt.DisplayRole: - return (self.py_name + ' [%d]'%len(self.child_tags())) + return self.py_name if role == Qt.EditRole: return (self.py_name) if role == Qt.DecorationRole: @@ -166,6 +167,8 @@ class TagTreeItem(object): # {{{ if role == DRAG_IMAGE_ROLE: self.ensure_icon() return self.icon_state_map[0] + if role == COUNT_ROLE: + return len(self.child_tags()) return None def tag_data(self, role): @@ -178,11 +181,7 @@ class TagTreeItem(object): # {{{ else: name = tag.name if role == Qt.DisplayRole: - count = self.item_count - if count == 0: - return ('%s'%(name)) - else: - return ('[%d] %s'%(count, name)) + return unicode(name) if role == Qt.EditRole: return (tag.original_name) if role == Qt.DecorationRole: @@ -202,10 +201,14 @@ class TagTreeItem(object): # {{{ tt.append(_('Books in this category are unrated')) if self.type == self.TAG and self.tag.category == 'search': 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) if role == DRAG_IMAGE_ROLE: self.ensure_icon() return self.icon_state_map[0] + if role == COUNT_ROLE: + return self.item_count return None def dump_data(self): diff --git a/src/calibre/gui2/tag_browser/view.py b/src/calibre/gui2/tag_browser/view.py index 19912bac89..056da9dbc5 100644 --- a/src/calibre/gui2/tag_browser/view.py +++ b/src/calibre/gui2/tag_browser/view.py @@ -11,14 +11,16 @@ import cPickle, os from functools import partial from itertools import izip -from PyQt5.Qt import (QStyledItemDelegate, Qt, QTreeView, pyqtSignal, QSize, - QIcon, QApplication, QMenu, QPoint, QModelIndex, QToolTip, QCursor, - QDrag) +from PyQt5.Qt import ( + QStyledItemDelegate, Qt, QTreeView, pyqtSignal, QSize, QIcon, QApplication, + QMenu, QPoint, QModelIndex, QToolTip, QCursor, QDrag, QRect, + QLinearGradient, QPalette, QColor, QPen, QBrush +) from calibre import sanitize_file_name_unicode from calibre.constants import config_dir 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.utils.icu import sort_key @@ -28,43 +30,73 @@ class TagDelegate(QStyledItemDelegate): # {{{ QStyledItemDelegate.__init__(self, *args, **kwargs) 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): item = index.data(Qt.UserRole) - QStyledItemDelegate.paint(self, painter, option, index) + QStyledItemDelegate.paint(self, painter, option, QModelIndex()) widget = self.parent() style = QApplication.style() if widget is None else widget.style() self.initStyleOption(option, index) + self.draw_icon(style, painter, option, widget) + self.draw_text(style, painter, option, widget, index, item) if item.boxed: r = style.subElementRect(style.SE_ItemViewItemFocusRect, option, widget) - painter.save() painter.drawLine(r.bottomLeft(), r.bottomRight()) - painter.restore() if item.type != TagTreeItem.TAG: return - if item.tag.state == 0 and config['show_avg_rating']: - 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() + if item.tag.state == 0: + if config['show_avg_rating']: + self.draw_average_rating(item, style, painter, option, widget) # }}}