mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Two things:
1) Fixes for the icon clicks. It now works when items are painted out of order. Resizing is now accounted for. Toggling and setting item focus now works properly. 2) Added items to the tag browser config menu, including the possibility of shortcuts.
This commit is contained in:
parent
91a46f99a9
commit
88dc2d85d3
@ -779,12 +779,26 @@ class TagBrowserWidget(QFrame): # {{{
|
|||||||
_('Configure Tag browser'), default_keys=(),
|
_('Configure Tag browser'), default_keys=(),
|
||||||
action=ac, group=_('Tag browser'))
|
action=ac, group=_('Tag browser'))
|
||||||
ac.triggered.connect(l.showMenu)
|
ac.triggered.connect(l.showMenu)
|
||||||
|
|
||||||
l.m.aboutToShow.connect(self.about_to_show_configure_menu)
|
l.m.aboutToShow.connect(self.about_to_show_configure_menu)
|
||||||
|
# Show/hide counts
|
||||||
l.m.show_counts_action = ac = l.m.addAction('counts')
|
l.m.show_counts_action = ac = l.m.addAction('counts')
|
||||||
ac.triggered.connect(self.toggle_counts)
|
ac.triggered.connect(self.toggle_counts)
|
||||||
|
# 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)
|
||||||
|
# Show/hide 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)
|
||||||
|
parent.keyboard.register_shortcut('tag browser toggle notes',
|
||||||
|
_('Toggle notes icons'), default_keys=(),
|
||||||
|
action=ac, group=_('Tag browser'))
|
||||||
|
# Show/hide links icon
|
||||||
|
l.m.show_links_icon_action = ac = l.m.addAction(QIcon.ic('external-link.png'), 'links icon')
|
||||||
|
ac.triggered.connect(self.toggle_links_icon)
|
||||||
|
parent.keyboard.register_shortcut('tag browser toggle links',
|
||||||
|
_('Toggle links icons'), default_keys=(),
|
||||||
|
action=ac, group=_('Tag browser'))
|
||||||
|
|
||||||
sb = l.m.addAction(QIcon.ic('sort.png'), _('Sort by'))
|
sb = l.m.addAction(QIcon.ic('sort.png'), _('Sort by'))
|
||||||
sb.m = l.sort_menu = QMenu(l.m)
|
sb.m = l.sort_menu = QMenu(l.m)
|
||||||
sb.setMenu(sb.m)
|
sb.setMenu(sb.m)
|
||||||
@ -858,6 +872,12 @@ class TagBrowserWidget(QFrame): # {{{
|
|||||||
ac = self.alter_tb.m.show_avg_rating_action
|
ac = self.alter_tb.m.show_avg_rating_action
|
||||||
ac.setText(_('Hide average rating') if config['show_avg_rating'] else _('Show average rating'))
|
ac.setText(_('Hide average rating') if config['show_avg_rating'] else _('Show average rating'))
|
||||||
ac.setIcon(QIcon.ic('minus.png' if config['show_avg_rating'] else 'plus.png'))
|
ac.setIcon(QIcon.ic('minus.png' if config['show_avg_rating'] else 'plus.png'))
|
||||||
|
ac = self.alter_tb.m.show_notes_icon_action
|
||||||
|
ac.setText(_('Hide notes icon') if gprefs['show_notes_in_tag_brouser'] else _('Show notes icon'))
|
||||||
|
ac.setIcon(QIcon.ic('minus.png' if gprefs['show_notes_in_tag_brouser'] else 'plus.png'))
|
||||||
|
ac = self.alter_tb.m.show_links_icon_action
|
||||||
|
ac.setText(_('Hide links icon') if gprefs['show_links_in_tag_brouser'] else _('Show links icon'))
|
||||||
|
ac.setIcon(QIcon.ic('minus.png' if gprefs['show_links_in_tag_brouser'] else 'plus.png'))
|
||||||
|
|
||||||
def filter_book_list(self):
|
def filter_book_list(self):
|
||||||
self.tags_view.model().set_in_tag_browser()
|
self.tags_view.model().set_in_tag_browser()
|
||||||
@ -865,9 +885,19 @@ class TagBrowserWidget(QFrame): # {{{
|
|||||||
|
|
||||||
def toggle_counts(self):
|
def toggle_counts(self):
|
||||||
gprefs['tag_browser_show_counts'] ^= True
|
gprefs['tag_browser_show_counts'] ^= True
|
||||||
|
self.tags_view.recount_with_position_based_index()
|
||||||
|
|
||||||
def toggle_avg_rating(self):
|
def toggle_avg_rating(self):
|
||||||
config['show_avg_rating'] ^= True
|
config['show_avg_rating'] ^= True
|
||||||
|
self.tags_view.recount_with_position_based_index()
|
||||||
|
|
||||||
|
def toggle_notes_icon(self):
|
||||||
|
gprefs['show_notes_in_tag_brouser'] ^= True
|
||||||
|
self.tags_view.recount_with_position_based_index()
|
||||||
|
|
||||||
|
def toggle_links_icon(self):
|
||||||
|
gprefs['show_links_in_tag_brouser'] ^= True
|
||||||
|
self.tags_view.recount_with_position_based_index()
|
||||||
|
|
||||||
def save_state(self):
|
def save_state(self):
|
||||||
gprefs.set('tag browser search box visible', self.toggle_search_button.isChecked())
|
gprefs.set('tag browser search box visible', self.toggle_search_button.isChecked())
|
||||||
|
@ -8,6 +8,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
|
from collections import defaultdict
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from qt.core import (
|
from qt.core import (
|
||||||
@ -95,22 +96,22 @@ class TagDelegate(QStyledItemDelegate): # {{{
|
|||||||
if item.type == TagTreeItem.TAG:
|
if item.type == TagTreeItem.TAG:
|
||||||
category = item.tag.category
|
category = item.tag.category
|
||||||
name = item.tag.original_name
|
name = item.tag.original_name
|
||||||
m = self.tags_view._model
|
tv = self.tags_view
|
||||||
if show_notes and m.category_has_notes(category):
|
m = tv._model
|
||||||
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)
|
|
||||||
self.tags_view.current_note_button_position = (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_links and m.category_has_links(category):
|
if show_links and m.category_has_links(category):
|
||||||
icon = self.links_icon if m.item_has_link(category, name) else self.blank_icon
|
icon = self.links_icon if m.item_has_link(category, name) else self.blank_icon
|
||||||
width = int(tr.height()/2)
|
width = int(tr.height()/2)
|
||||||
r = QRect(tr)
|
r = QRect(tr)
|
||||||
r.setRight(r.right() - 1), r.setLeft(r.right() - width - 4)
|
r.setRight(r.right() - 1), r.setLeft(r.right() - width - 4)
|
||||||
self.tags_view.current_link_button_position = (r.left(), r.left()+r.width())
|
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)
|
icon.paint(painter, r, option.decorationAlignment, QIcon.Mode.Normal, QIcon.State.On)
|
||||||
tr.setRight(r.left() - 1)
|
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']):
|
||||||
@ -229,8 +230,6 @@ class TagsView(QTreeView): # {{{
|
|||||||
self.setTabKeyNavigation(True)
|
self.setTabKeyNavigation(True)
|
||||||
self.setAnimated(True)
|
self.setAnimated(True)
|
||||||
self.setHeaderHidden(True)
|
self.setHeaderHidden(True)
|
||||||
self.current_note_button_position = (-1, -1)
|
|
||||||
self.current_link_button_position = (-1, -1)
|
|
||||||
self.setItemDelegate(TagDelegate(tags_view=self))
|
self.setItemDelegate(TagDelegate(tags_view=self))
|
||||||
self.made_connections = False
|
self.made_connections = False
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
@ -248,6 +247,12 @@ class TagsView(QTreeView): # {{{
|
|||||||
self.plus_icon = QIcon.ic('plus.png')
|
self.plus_icon = QIcon.ic('plus.png')
|
||||||
self.minus_icon = QIcon.ic('minus.png')
|
self.minus_icon = QIcon.ic('minus.png')
|
||||||
|
|
||||||
|
# Dict for recording the positions of the fake buttons for category tag
|
||||||
|
# lines. It is recorded per category because we can't guarantee the
|
||||||
|
# order that items are painted. The numbers get updated whenever an item
|
||||||
|
# is painted, which deals with resizing.
|
||||||
|
self.category_button_positions = defaultdict(dict)
|
||||||
|
|
||||||
self._model = TagsModel(self)
|
self._model = TagsModel(self)
|
||||||
self._model.search_item_renamed.connect(self.search_item_renamed)
|
self._model.search_item_renamed.connect(self.search_item_renamed)
|
||||||
self._model.refresh_required.connect(self.refresh_required,
|
self._model.refresh_required.connect(self.refresh_required,
|
||||||
@ -361,7 +366,7 @@ class TagsView(QTreeView): # {{{
|
|||||||
match_pop = 0
|
match_pop = 0
|
||||||
self.alter_tb.match_menu.actions()[match_pop].setChecked(True)
|
self.alter_tb.match_menu.actions()[match_pop].setChecked(True)
|
||||||
if not self.made_connections:
|
if not self.made_connections:
|
||||||
self.clicked.connect(self.toggle)
|
self.clicked.connect(self.toggle_on_mouse_click)
|
||||||
self.customContextMenuRequested.connect(self.show_context_menu)
|
self.customContextMenuRequested.connect(self.show_context_menu)
|
||||||
self.refresh_required.connect(self.recount, type=Qt.ConnectionType.QueuedConnection)
|
self.refresh_required.connect(self.recount, type=Qt.ConnectionType.QueuedConnection)
|
||||||
self.alter_tb.sort_menu.triggered.connect(self.sort_changed)
|
self.alter_tb.sort_menu.triggered.connect(self.sort_changed)
|
||||||
@ -457,29 +462,12 @@ class TagsView(QTreeView): # {{{
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def number_in_range(self, val, range_tuple):
|
|
||||||
return range_tuple[0] <= val <= range_tuple[1]
|
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
def mousePressEvent(self, event):
|
||||||
if event.buttons() & Qt.MouseButton.LeftButton:
|
if event.buttons() & Qt.MouseButton.LeftButton:
|
||||||
|
# Record the press point for processing during the clicked signal
|
||||||
|
self.mouse_clicked_point = event.pos()
|
||||||
# Only remember a possible drag start if the item is drag enabled
|
# Only remember a possible drag start if the item is drag enabled
|
||||||
dex = self.indexAt(event.pos())
|
dex = self.indexAt(event.pos())
|
||||||
t = self._model.data(dex, Qt.UserRole)
|
|
||||||
if t.type == TagTreeItem.TAG:
|
|
||||||
db = self._model.db.new_api
|
|
||||||
tag = t.tag
|
|
||||||
x = event.pos().x()
|
|
||||||
if self.number_in_range(x, self.current_note_button_position):
|
|
||||||
from calibre.gui2.dialogs.show_category_note import ShowNoteDialog
|
|
||||||
item_id = db.get_item_id(tag.category, tag.original_name)
|
|
||||||
if db.notes_for(tag.category, item_id):
|
|
||||||
ShowNoteDialog(tag.category, item_id, db, parent=self).show()
|
|
||||||
return
|
|
||||||
elif self.number_in_range(x, self.current_link_button_position):
|
|
||||||
link = db.get_link_map(tag.category).get(tag.original_name)
|
|
||||||
if link:
|
|
||||||
safe_open_url(link)
|
|
||||||
return
|
|
||||||
if self._model.flags(dex) & Qt.ItemFlag.ItemIsDragEnabled:
|
if self._model.flags(dex) & Qt.ItemFlag.ItemIsDragEnabled:
|
||||||
self.possible_drag_start = event.pos()
|
self.possible_drag_start = event.pos()
|
||||||
else:
|
else:
|
||||||
@ -534,11 +522,37 @@ 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):
|
||||||
|
range_tuple = self.category_button_positions[category].get(kind)
|
||||||
|
return range_tuple and range_tuple[0] <= val <= range_tuple[1]
|
||||||
|
|
||||||
def toggle_current_index(self):
|
def toggle_current_index(self):
|
||||||
ci = self.currentIndex()
|
ci = self.currentIndex()
|
||||||
if ci.isValid():
|
if ci.isValid():
|
||||||
self.toggle(ci)
|
self.toggle(ci)
|
||||||
|
|
||||||
|
def toggle_on_mouse_click(self, index):
|
||||||
|
# Check if one of the link or note icons was clicked. If so, deal with
|
||||||
|
# it here and don't do the real toggle
|
||||||
|
t = self._model.data(index, Qt.UserRole)
|
||||||
|
if t.type == TagTreeItem.TAG:
|
||||||
|
db = self._model.db.new_api
|
||||||
|
category = t.tag.category
|
||||||
|
orig_name = t.tag.original_name
|
||||||
|
x = self.mouse_clicked_point.x()
|
||||||
|
if self.click_in_button_range(x, category, 'notes'):
|
||||||
|
from calibre.gui2.dialogs.show_category_note import ShowNoteDialog
|
||||||
|
item_id = db.get_item_id(category, orig_name)
|
||||||
|
if db.notes_for(category, item_id):
|
||||||
|
ShowNoteDialog(category, item_id, db, parent=self).show()
|
||||||
|
return
|
||||||
|
if self.click_in_button_range(x, category, 'links'):
|
||||||
|
link = db.get_link_map(category).get(orig_name)
|
||||||
|
if link:
|
||||||
|
safe_open_url(link)
|
||||||
|
return
|
||||||
|
self._toggle(index, None)
|
||||||
|
|
||||||
def toggle(self, index):
|
def toggle(self, index):
|
||||||
self._toggle(index, None)
|
self._toggle(index, None)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user