mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Two changes related to the icons in tag browser:
1) Add the capability to show the icons next to the text, unaligned. Set via an option in look&feel. This change required recording the icon position on a per-item basis instead of a per-category basis. 2) Add the possibility of keyboard shortcuts to "show counts" and "show average rating" so they are the same as the show icons ones.
This commit is contained in:
parent
bac8192571
commit
a1809bcaea
@ -425,6 +425,7 @@ def create_defs():
|
|||||||
defs['allow_keyboard_search_in_library_views'] = True
|
defs['allow_keyboard_search_in_library_views'] = True
|
||||||
defs['show_links_in_tag_browser'] = False
|
defs['show_links_in_tag_browser'] = False
|
||||||
defs['show_notes_in_tag_browser'] = False
|
defs['show_notes_in_tag_browser'] = False
|
||||||
|
defs['icons_on_right_in_tag_browser'] = True
|
||||||
|
|
||||||
def migrate_tweak(tweak_name, pref_name):
|
def migrate_tweak(tweak_name, pref_name):
|
||||||
# If the tweak has been changed then leave the tweak in the file so
|
# If the tweak has been changed then leave the tweak in the file so
|
||||||
|
@ -648,6 +648,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
r('show_avg_rating', config)
|
r('show_avg_rating', config)
|
||||||
r('show_links_in_tag_browser', gprefs)
|
r('show_links_in_tag_browser', gprefs)
|
||||||
r('show_notes_in_tag_browser', gprefs)
|
r('show_notes_in_tag_browser', gprefs)
|
||||||
|
r('icons_on_right_in_tag_browser', gprefs)
|
||||||
r('disable_animations', config)
|
r('disable_animations', config)
|
||||||
r('systray_icon', config, restart_required=True)
|
r('systray_icon', config, restart_required=True)
|
||||||
r('show_splash_screen', gprefs)
|
r('show_splash_screen', gprefs)
|
||||||
|
@ -1370,6 +1370,21 @@ box will cause these empty categories to be hidden.</p></string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QCheckBox" name="opt_icons_on_right_in_tag_browser">
|
||||||
|
<property name="text">
|
||||||
|
<string>Place icons on the &right, in columns</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>If checked the notes and links icons will be placed at the right, after
|
||||||
|
the count and in columns. If unchecked, the icons will be placed immediately after the text,
|
||||||
|
to the left of the count and not in columns.</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="2" column="2">
|
<item row="2" column="2">
|
||||||
<widget class="QCheckBox" name="opt_tag_browser_always_autocollapse">
|
<widget class="QCheckBox" name="opt_tag_browser_always_autocollapse">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
|
@ -782,10 +782,16 @@ class TagBrowserWidget(QFrame): # {{{
|
|||||||
l.m.aboutToShow.connect(self.about_to_show_configure_menu)
|
l.m.aboutToShow.connect(self.about_to_show_configure_menu)
|
||||||
# Show/hide counts
|
# Show/hide counts
|
||||||
l.m.show_counts_action = ac = l.m.addAction('counts')
|
l.m.show_counts_action = ac = l.m.addAction('counts')
|
||||||
|
parent.keyboard.register_shortcut('tag browser toggle counts',
|
||||||
|
_('Toggle counts'), default_keys=(),
|
||||||
|
action=ac, group=_('Tag browser'))
|
||||||
ac.triggered.connect(self.toggle_counts)
|
ac.triggered.connect(self.toggle_counts)
|
||||||
# Show/hide average rating
|
# Show/hide average rating
|
||||||
l.m.show_avg_rating_action = ac = l.m.addAction(QIcon.ic('rating.png'), 'avg rating')
|
l.m.show_avg_rating_action = ac = l.m.addAction(QIcon.ic('rating.png'), 'avg rating')
|
||||||
ac.triggered.connect(self.toggle_avg_rating)
|
ac.triggered.connect(self.toggle_avg_rating)
|
||||||
|
parent.keyboard.register_shortcut('tag browser toggle average ratings',
|
||||||
|
_('Toggle average ratings'), default_keys=(),
|
||||||
|
action=ac, group=_('Tag browser'))
|
||||||
# Show/hide notes icon
|
# Show/hide notes icon
|
||||||
l.m.show_notes_icon_action = ac = l.m.addAction(QIcon.ic('notes.png'), 'notes icon')
|
l.m.show_notes_icon_action = ac = l.m.addAction(QIcon.ic('notes.png'), 'notes icon')
|
||||||
ac.triggered.connect(self.toggle_notes_icon)
|
ac.triggered.connect(self.toggle_notes_icon)
|
||||||
|
@ -87,33 +87,15 @@ class TagDelegate(QStyledItemDelegate): # {{{
|
|||||||
def draw_text(self, style, painter, option, widget, index, item):
|
def draw_text(self, style, painter, option, widget, index, item):
|
||||||
tr = style.subElementRect(QStyle.SubElement.SE_ItemViewItemText, option, widget)
|
tr = style.subElementRect(QStyle.SubElement.SE_ItemViewItemText, option, widget)
|
||||||
text = index.data(Qt.ItemDataRole.DisplayRole)
|
text = index.data(Qt.ItemDataRole.DisplayRole)
|
||||||
|
flags = Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignLeft | Qt.TextFlag.TextSingleLine
|
||||||
|
lr = QRect(tr)
|
||||||
|
lr.setRight(lr.right() * 2)
|
||||||
|
text_rec = painter.boundingRect(lr, flags, text)
|
||||||
hover = option.state & QStyle.StateFlag.State_MouseOver
|
hover = option.state & QStyle.StateFlag.State_MouseOver
|
||||||
is_search = (True if item.type == TagTreeItem.TAG and
|
is_search = (True if item.type == TagTreeItem.TAG and
|
||||||
item.tag.category == 'search' else False)
|
item.tag.category == 'search' else False)
|
||||||
|
|
||||||
show_notes = gprefs['show_notes_in_tag_browser']
|
def render_count():
|
||||||
show_links = gprefs['show_links_in_tag_browser']
|
|
||||||
if item.type == TagTreeItem.TAG:
|
|
||||||
category = item.tag.category
|
|
||||||
name = item.tag.original_name
|
|
||||||
tv = self.tags_view
|
|
||||||
m = tv._model
|
|
||||||
if show_links and m.category_has_links(category):
|
|
||||||
icon = self.links_icon if m.item_has_link(category, name) else self.blank_icon
|
|
||||||
width = int(tr.height()/2)
|
|
||||||
r = QRect(tr)
|
|
||||||
r.setRight(r.right() - 1), r.setLeft(r.right() - width - 4)
|
|
||||||
tv.category_button_positions[category]['links'] = (r.left(), r.left()+r.width())
|
|
||||||
icon.paint(painter, r, option.decorationAlignment, QIcon.Mode.Normal, QIcon.State.On)
|
|
||||||
tr.setRight(r.left() - 1)
|
|
||||||
if show_notes and m.category_has_notes(category):
|
|
||||||
icon = self.notes_icon if m.item_has_note(category, name) else self.blank_icon
|
|
||||||
width = int(tr.height()/2)
|
|
||||||
r = QRect(tr)
|
|
||||||
r.setRight(r.right() - 1), r.setLeft(r.right() - width - 4)
|
|
||||||
tv.category_button_positions[category]['notes'] = (r.left(), r.left()+r.width())
|
|
||||||
icon.paint(painter, r, option.decorationAlignment, QIcon.Mode.Normal, QIcon.State.On)
|
|
||||||
tr.setRight(r.left() - 1)
|
|
||||||
if not is_search and (hover or gprefs['tag_browser_show_counts']):
|
if not is_search and (hover or gprefs['tag_browser_show_counts']):
|
||||||
count = str(index.data(COUNT_ROLE))
|
count = str(index.data(COUNT_ROLE))
|
||||||
width = painter.fontMetrics().boundingRect(count).width()
|
width = painter.fontMetrics().boundingRect(count).width()
|
||||||
@ -123,14 +105,68 @@ class TagDelegate(QStyledItemDelegate): # {{{
|
|||||||
tr.setRight(r.left() - 1)
|
tr.setRight(r.left() - 1)
|
||||||
else:
|
else:
|
||||||
tr.setRight(tr.right() - 1)
|
tr.setRight(tr.right() - 1)
|
||||||
|
|
||||||
|
if item.type == TagTreeItem.TAG:
|
||||||
|
category = item.tag.category
|
||||||
|
name = item.tag.original_name
|
||||||
|
tv = self.tags_view
|
||||||
|
m = tv._model
|
||||||
|
positions = {'links': (-1, -1), 'notes': (-1, -1)}
|
||||||
|
|
||||||
|
# The icons fits in a rectangle height/2 + 4 x height/2 + 4. This
|
||||||
|
# ensures they are a 'pleasant' size compared to the text.
|
||||||
|
icon_width = int(tr.height()/2) + 4
|
||||||
|
|
||||||
|
def render_link_icon():
|
||||||
|
icon = self.links_icon if m.item_has_link(category, name) else self.blank_icon
|
||||||
|
r = QRect(tr)
|
||||||
|
r.setRight(r.right() - 1)
|
||||||
|
r.setLeft(r.right() - icon_width)
|
||||||
|
positions['links'] = (r.left(), r.left()+r.width())
|
||||||
|
icon.paint(painter, r, option.decorationAlignment, QIcon.Mode.Normal, QIcon.State.On)
|
||||||
|
tr.setRight(r.left() - 1)
|
||||||
|
def render_note_icon():
|
||||||
|
icon = self.notes_icon if m.item_has_note(category, name) else self.blank_icon
|
||||||
|
r = QRect(tr)
|
||||||
|
r.setRight(r.right() - 1)
|
||||||
|
r.setLeft(r.right() - icon_width)
|
||||||
|
positions['notes'] = (r.left(), r.left()+r.width())
|
||||||
|
icon.paint(painter, r, option.decorationAlignment, QIcon.Mode.Normal, QIcon.State.On)
|
||||||
|
tr.setRight(r.left() - 1)
|
||||||
|
|
||||||
|
if gprefs['icons_on_right_in_tag_browser']:
|
||||||
|
# Icons go far right, in columns after the counts
|
||||||
|
show_note_icon = gprefs['show_notes_in_tag_browser'] and m.category_has_notes(category)
|
||||||
|
show_link_icon = gprefs['show_links_in_tag_browser'] and m.category_has_links(category)
|
||||||
|
if show_link_icon:
|
||||||
|
render_link_icon()
|
||||||
|
if show_note_icon:
|
||||||
|
render_note_icon()
|
||||||
|
render_count()
|
||||||
|
else:
|
||||||
|
# Icons go after the text to the left of the counts, not in columns
|
||||||
|
show_note_icon = gprefs['show_notes_in_tag_browser'] and m.item_has_note(category, name)
|
||||||
|
show_link_icon = gprefs['show_links_in_tag_browser'] and m.item_has_link(category, name)
|
||||||
|
|
||||||
|
render_count()
|
||||||
|
# The link icon has a margin of 1 px on each side. Account for
|
||||||
|
# this when computing the width of the icons. If you change the
|
||||||
|
# order of the icons then you must change this calculation
|
||||||
|
w = (int(show_link_icon) * (icon_width + 2)) + (int(show_note_icon) * icon_width)
|
||||||
|
# Leave a 5 px margin between the text and the icon.
|
||||||
|
tr.setWidth(min(tr.width(), text_rec.width() + 5 + w))
|
||||||
|
if show_link_icon:
|
||||||
|
render_link_icon()
|
||||||
|
if show_note_icon:
|
||||||
|
render_note_icon()
|
||||||
|
tv.category_button_positions[category][name] = positions
|
||||||
|
else:
|
||||||
|
render_count()
|
||||||
|
|
||||||
is_rating = item.type == TagTreeItem.TAG and not self.rating_pat.sub('', text)
|
is_rating = item.type == TagTreeItem.TAG and not self.rating_pat.sub('', text)
|
||||||
if is_rating:
|
if is_rating:
|
||||||
painter.setFont(self.rating_font)
|
painter.setFont(self.rating_font)
|
||||||
flags = Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignLeft | Qt.TextFlag.TextSingleLine
|
if text_rec.width() > tr.width():
|
||||||
lr = QRect(tr)
|
|
||||||
lr.setRight(lr.right() * 2)
|
|
||||||
br = painter.boundingRect(lr, flags, text)
|
|
||||||
if br.width() > tr.width():
|
|
||||||
g = QLinearGradient(QPointF(tr.topLeft()), QPointF(tr.topRight()))
|
g = QLinearGradient(QPointF(tr.topLeft()), QPointF(tr.topRight()))
|
||||||
c = option.palette.color(QPalette.ColorRole.WindowText)
|
c = option.palette.color(QPalette.ColorRole.WindowText)
|
||||||
g.setColorAt(0, c), g.setColorAt(0.8, c)
|
g.setColorAt(0, c), g.setColorAt(0.8, c)
|
||||||
@ -522,8 +558,8 @@ class TagsView(QTreeView): # {{{
|
|||||||
joiner = ' and ' if self.match_all else ' or '
|
joiner = ' and ' if self.match_all else ' or '
|
||||||
return joiner.join(tokens)
|
return joiner.join(tokens)
|
||||||
|
|
||||||
def click_in_button_range(self, val, category, kind):
|
def click_in_button_range(self, val, category, item_name, kind):
|
||||||
range_tuple = self.category_button_positions[category].get(kind)
|
range_tuple = self.category_button_positions[category].get(item_name, {}).get(kind)
|
||||||
return range_tuple and range_tuple[0] <= val <= range_tuple[1]
|
return range_tuple and range_tuple[0] <= val <= range_tuple[1]
|
||||||
|
|
||||||
def toggle_current_index(self):
|
def toggle_current_index(self):
|
||||||
@ -540,13 +576,13 @@ class TagsView(QTreeView): # {{{
|
|||||||
category = t.tag.category
|
category = t.tag.category
|
||||||
orig_name = t.tag.original_name
|
orig_name = t.tag.original_name
|
||||||
x = self.mouse_clicked_point.x()
|
x = self.mouse_clicked_point.x()
|
||||||
if self.click_in_button_range(x, category, 'notes'):
|
if self.click_in_button_range(x, category, orig_name, 'notes'):
|
||||||
from calibre.gui2.dialogs.show_category_note import ShowNoteDialog
|
from calibre.gui2.dialogs.show_category_note import ShowNoteDialog
|
||||||
item_id = db.get_item_id(category, orig_name)
|
item_id = db.get_item_id(category, orig_name)
|
||||||
if db.notes_for(category, item_id):
|
if db.notes_for(category, item_id):
|
||||||
ShowNoteDialog(category, item_id, db, parent=self).show()
|
ShowNoteDialog(category, item_id, db, parent=self).show()
|
||||||
return
|
return
|
||||||
if self.click_in_button_range(x, category, 'links'):
|
if self.click_in_button_range(x, category, orig_name, 'links'):
|
||||||
link = db.get_link_map(category).get(orig_name)
|
link = db.get_link_map(category).get(orig_name)
|
||||||
if link:
|
if link:
|
||||||
safe_open_url(link)
|
safe_open_url(link)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user