diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py
index 25daf9862c..6324320005 100644
--- a/src/calibre/gui2/__init__.py
+++ b/src/calibre/gui2/__init__.py
@@ -152,6 +152,7 @@ def create_defs():
defs['tag_browser_old_look'] = False
defs['tag_browser_hide_empty_categories'] = False
defs['tag_browser_always_autocollapse'] = False
+ defs['tag_browser_allow_keyboard_focus'] = False
defs['book_list_tooltips'] = True
defs['show_layout_buttons'] = False
defs['bd_show_cover'] = True
diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py
index 5445ca38f1..e798946eb6 100644
--- a/src/calibre/gui2/preferences/look_feel.py
+++ b/src/calibre/gui2/preferences/look_feel.py
@@ -414,6 +414,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
r('tag_browser_hide_empty_categories', gprefs)
r('tag_browser_always_autocollapse', gprefs)
r('tag_browser_show_tooltips', gprefs)
+ r('tag_browser_allow_keyboard_focus', gprefs, restart_required=True)
r('bd_show_cover', gprefs)
r('bd_overlay_cover_size', gprefs)
r('cover_grid_width', gprefs)
diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui
index 37e4c58606..e11a68cb81 100644
--- a/src/calibre/gui2/preferences/look_feel.ui
+++ b/src/calibre/gui2/preferences/look_feel.ui
@@ -893,6 +893,27 @@ A value of zero means calculate automatically.
QFormLayout::ExpandingFieldsGrow
+ -
+
+
+ Choose how Tag browser subcategories are displayed when
+there are more items than the limit. Select by first
+letter to see an A, B, C list. Choose partitioned to
+have a list of fixed-sized groups. Set to disabled
+if you never want subcategories
+
+
+
+ -
+
+
+ &Category partitioning method:
+
+
+ opt_tags_browser_partition_method
+
+
+
-
@@ -939,6 +960,38 @@ not set to first letter, this value is ignored. Set to zero to disable.
+ -
+
+
+ Spacing between &items:
+
+
+ opt_tag_browser_item_padding
+
+
+
+ -
+
+
+ The spacing between consecutive items in the Tag browser. In units of (ex) which is the approximate height of the letter 'x' in the currently used font.
+
+
+ ex
+
+
+ 1
+
+
+ -1.000000000000000
+
+
+ 2.000000000000000
+
+
+ 0.100000000000000
+
+
+
-
@@ -994,6 +1047,35 @@ then the tags will be displayed each on their own line.
+ -
+
+
+ Show &tooltips
+
+
+
+ -
+
+
+ Show &average ratings
+
+
+ true
+
+
+
+ -
+
+
+ Show counts for items in the Tag browser. Such as the number of books
+by each author, the number of authors, etc. If you turn it off, you can still
+see the counts by hovering your mouse over any item.
+
+
+ Show &counts
+
+
+
-
@@ -1026,85 +1108,17 @@ then the tags will be displayed each on their own line.
- -
-
+
-
+
+
+ Allow the Tag browser to have keyboard focus (needs restart)
+
- Choose how Tag browser subcategories are displayed when
-there are more items than the limit. Select by first
-letter to see an A, B, C list. Choose partitioned to
-have a list of fixed-sized groups. Set to disabled
-if you never want subcategories
-
-
-
- -
-
-
- &Category partitioning method:
-
-
- opt_tags_browser_partition_method
-
-
-
- -
-
-
- Show &average ratings
-
-
- true
-
-
-
- -
-
-
- Show counts for items in the Tag browser. Such as the number of books
-by each author, the number of authors, etc. If you turn it off, you can still
-see the counts by hovering your mouse over any item.
-
-
- Show &counts
-
-
-
- -
-
-
- Spacing between &items:
-
-
- opt_tag_browser_item_padding
-
-
-
- -
-
-
- The spacing between consecutive items in the Tag browser. In units of (ex) which is the approximate height of the letter 'x' in the currently used font.
-
-
- ex
-
-
- 1
-
-
- -1.000000000000000
-
-
- 2.000000000000000
-
-
- 0.100000000000000
-
-
-
- -
-
-
- Show &tooltips
+ <p>When checked, the Tag browser can get keyboard focus, allowing
+use of the keyboard to navigate the tree using the arrow keys. The RETURN key simulates
+a click on the selected item. The keyboard shortcut 'Tag browser /
+Give the Tag browser keyboard focus' changes the keyboard focus without
+using the mouse.</p>
diff --git a/src/calibre/gui2/tag_browser/ui.py b/src/calibre/gui2/tag_browser/ui.py
index ef1a95b768..c182b13626 100644
--- a/src/calibre/gui2/tag_browser/ui.py
+++ b/src/calibre/gui2/tag_browser/ui.py
@@ -661,6 +661,13 @@ class TagBrowserWidget(QFrame): # {{{
action=ac, group=_('Tag browser'))
ac.triggered.connect(self.toggle_item)
+ ac = QAction(parent)
+ parent.addAction(ac)
+ parent.keyboard.register_shortcut('tag browser set focus',
+ _("Give the Tag browser keyboard focus"), default_keys=(),
+ action=ac, group=_('Tag browser'))
+ ac.triggered.connect(self.give_tb_focus)
+
# self.leak_test_timer = QTimer(self)
# self.leak_test_timer.timeout.connect(self.test_for_leak)
# self.leak_test_timer.start(5000)
@@ -671,6 +678,15 @@ class TagBrowserWidget(QFrame): # {{{
def toggle_item(self):
self.tags_view.toggle_current_index()
+ def give_tb_focus(self, *args):
+ if gprefs['tag_browser_allow_keyboard_focus']:
+ tb = self.tags_view
+ idx = tb.currentIndex()
+ if not idx.isValid:
+ idx = tb.model().createIndex(0, 0)
+ tb.setCurrentIndex(idx)
+ tb.setFocus(Qt.OtherFocusReason)
+
def set_pane_is_visible(self, to_what):
self.tags_view.set_pane_is_visible(to_what)
diff --git a/src/calibre/gui2/tag_browser/view.py b/src/calibre/gui2/tag_browser/view.py
index 7cb0fdc36b..738e8cf925 100644
--- a/src/calibre/gui2/tag_browser/view.py
+++ b/src/calibre/gui2/tag_browser/view.py
@@ -195,9 +195,8 @@ class TagsView(QTreeView): # {{{
type=Qt.QueuedConnection)
self._model.drag_drop_finished.connect(self.drag_drop_finished)
self.set_look_and_feel()
- # Allowing keyboard focus looks bad in the Qt Fusion style and is useless
- # anyway since the enter/spacebar keys do nothing
- self.setFocusPolicy(Qt.NoFocus)
+ if not gprefs['tag_browser_allow_keyboard_focus']:
+ self.setFocusPolicy(Qt.NoFocus)
QApplication.instance().palette_changed.connect(self.set_style_sheet, type=Qt.QueuedConnection)
def set_style_sheet(self):
@@ -291,6 +290,15 @@ class TagsView(QTreeView): # {{{
self.refresh_signal_processed = True
db.add_listener(self.database_changed)
self.expanded.connect(self.item_expanded)
+ self.collapsed.connect(self.collapse_node_and_children)
+
+ def keyPressEvent(self, event):
+ if event.key() == Qt.Key_Return:
+ # I don't see how it can ever not be valid, but ...
+ if self.currentIndex().isValid():
+ self.toggle_current_index()
+ return
+ QTreeView.keyPressEvent(self, event)
def database_changed(self, event, ids):
if self.refresh_signal_processed: