Allow changing the icons for categories in the Tag Browser. Right click on a category and choose 'Change category icon'. Fixes #1092098 (UserCategory Icons (Whishlist))

This commit is contained in:
Kovid Goyal 2012-12-21 00:02:22 +05:30
commit 30e073fbeb
3 changed files with 77 additions and 12 deletions

View File

@ -106,6 +106,7 @@ gprefs.defaults['tag_browser_old_look'] = False
gprefs.defaults['book_list_tooltips'] = True
gprefs.defaults['bd_show_cover'] = True
gprefs.defaults['bd_overlay_cover_size'] = False
gprefs.defaults['tags_browser_category_icons'] = {}
# }}}
NONE = QVariant() #: Null value to return from the data function of item models

View File

@ -8,11 +8,12 @@ __license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import traceback, cPickle, copy
import traceback, cPickle, copy, os
from PyQt4.Qt import (QAbstractItemModel, QIcon, QVariant, QFont, Qt,
QMimeData, QModelIndex, pyqtSignal, QObject)
from calibre.constants import config_dir
from calibre.gui2 import NONE, gprefs, config, error_dialog
from calibre.library.database2 import Tag
from calibre.utils.config import tweaks
@ -213,6 +214,11 @@ class TagsModel(QAbstractItemModel): # {{{
for key in category_icon_map:
iconmap[key] = QIcon(I(category_icon_map[key]))
self.category_icon_map = TagsIcons(iconmap)
self.category_custom_icons = dict()
for k, v in gprefs['tags_browser_category_icons'].iteritems():
icon = QIcon(os.path.join(config_dir, 'tb_icons', v))
if len(icon.availableSizes()) > 0:
self.category_custom_icons[k] = icon
self.categories_with_ratings = ['authors', 'series', 'publisher', 'tags']
self.icon_state_map = [None, QIcon(I('plus.png')), QIcon(I('plusplus.png')),
QIcon(I('minus.png')), QIcon(I('minusminus.png'))]
@ -231,6 +237,23 @@ class TagsModel(QAbstractItemModel): # {{{
def gui_parent(self):
return QObject.parent(self)
def set_custom_category_icon(self, key, path):
d = gprefs['tags_browser_category_icons']
if path:
d[key] = path
self.category_custom_icons[key] = QIcon(os.path.join(config_dir,
'tb_icons', path))
else:
if key in d:
path = os.path.join(config_dir, 'tb_icons', d[key])
try:
os.remove(path)
except:
pass
del d[key]
del self.category_custom_icons[key]
gprefs['tags_browser_category_icons'] = d
def reread_collapse_model(self, state_map, rebuild=True):
if gprefs['tags_browser_collapse_at'] == 0:
self.collapse_model = 'disable'
@ -304,13 +327,18 @@ class TagsModel(QAbstractItemModel): # {{{
continue
is_gst = False
if key.startswith('@') and key[1:] in gst:
tt = _(u'The grouped search term name is "{0}"').format(key[1:])
tt = _(u'The grouped search term name is "{0}"').format(key)
is_gst = True
elif key == 'news':
tt = ''
else:
tt = _(u'The lookup/search name is "{0}"').format(key)
if self.category_custom_icons.get(key, None) is None:
self.category_custom_icons[key] = (
self.category_icon_map['gst'] if is_gst else
self.category_icon_map.get(key, self.category_icon_map['custom:']))
if key.startswith('@'):
path_parts = [p for p in key.split('.')]
path = ''
@ -319,11 +347,9 @@ class TagsModel(QAbstractItemModel): # {{{
for i,p in enumerate(path_parts):
path += p
if path not in category_node_map:
icon = self.category_icon_map['gst'] if is_gst else \
self.category_icon_map[key]
node = self.create_node(parent=last_category_node,
data=p[1:] if i == 0 else p,
category_icon=icon,
category_icon=self.category_custom_icons[key],
tooltip=tt if path == key else path,
category_key=path,
icon_map=self.icon_state_map)
@ -343,7 +369,7 @@ class TagsModel(QAbstractItemModel): # {{{
else:
node = self.create_node(parent=self.root_item,
data=self.categories[key],
category_icon=self.category_icon_map[key],
category_icon=self.category_custom_icons[key],
tooltip=tt, category_key=key,
icon_map=self.icon_state_map)
node.is_gst = False
@ -504,6 +530,7 @@ class TagsModel(QAbstractItemModel): # {{{
if (not tag.is_hierarchical) and (in_uc or
(fm['is_custom'] and fm['display'].get('is_names', False)) or
not category_is_hierarchical or len(components) == 1):
tag.icon = self.category_custom_icons[key]
n = self.create_node(parent=node_parent, data=tag, tooltip=tt,
icon_map=self.icon_state_map)
if tag.id_set is not None:
@ -540,6 +567,7 @@ class TagsModel(QAbstractItemModel): # {{{
t.is_hierarchical = \
'5state' if t.category != 'search' else '3state'
t.name = comp
t.icon = self.category_custom_icons[key]
node_parent = self.create_node(parent=node_parent, data=t,
tooltip=tt, icon_map=self.icon_state_map)
child_map[(comp,tag.category)] = node_parent

View File

@ -7,7 +7,7 @@ __license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import cPickle
import cPickle, os
from functools import partial
from itertools import izip
@ -15,9 +15,11 @@ from PyQt4.Qt import (QStyledItemDelegate, Qt, QTreeView, pyqtSignal, QSize,
QIcon, QApplication, QMenu, QPoint, QModelIndex, QToolTip, QCursor,
QDrag)
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)
from calibre.gui2 import config, gprefs
from calibre.gui2 import config, gprefs, choose_files, pixmap_to_data
from calibre.utils.search_query_parser import saved_searches
from calibre.utils.icu import sort_key
@ -296,6 +298,33 @@ class TagsView(QTreeView): # {{{
if not action:
return
try:
if action == 'set_icon':
try:
path = choose_files(self, 'choose_category_icon',
_('Change Icon for: %s')%key, filters=[
('Images', ['png', 'gif', 'jpg', 'jpeg'])],
all_files=False, select_only_single_file=True)
if path:
path = path[0]
p = QIcon(path).pixmap(QSize(128, 128))
d = os.path.join(config_dir, 'tb_icons')
if not os.path.exists(d):
os.makedirs(d)
with open(os.path.join(d, 'icon_'+
sanitize_file_name_unicode(key)+'.png'), 'wb') as f:
f.write(pixmap_to_data(p, format='PNG'))
path = os.path.basename(f.name)
self._model.set_custom_category_icon(key, unicode(path))
self.recount()
except:
import traceback
traceback.print_exc()
return
if action == 'clear_icon':
self._model.set_custom_category_icon(key, None)
self.recount()
return
if action == 'edit_item':
self.edit(index)
return
@ -533,6 +562,12 @@ class TagsView(QTreeView): # {{{
partial(self.context_menu_handler, action='manage_searches',
category=tag.name if tag else None))
self.context_menu.addSeparator()
self.context_menu.addAction(_('Change category icon'),
partial(self.context_menu_handler, action='set_icon', key=key))
self.context_menu.addAction(_('Restore default icon'),
partial(self.context_menu_handler, action='clear_icon', key=key))
# Always show the user categories editor
self.context_menu.addSeparator()
if key.startswith('@') and \
@ -551,6 +586,7 @@ class TagsView(QTreeView): # {{{
self.context_menu.addAction(_('Show all categories'),
partial(self.context_menu_handler, action='defaults'))
m = self.context_menu.addMenu(_('Change sub-categorization scheme'))
da = m.addAction(_('Disable'),
partial(self.context_menu_handler, action='categorization', category='disable'))