This commit is contained in:
Kovid Goyal 2022-08-26 14:41:12 +05:30
commit d2d267a576
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 392 additions and 211 deletions

View File

@ -386,7 +386,7 @@ Two variants of equality searches are used for hierarchical items (e.g., A.B.C):
*'Regular expression' searches*
Regular expression searches are indicated by prefixing the search string with a tilde (~). Any `Python-compatible regular expression <https://docs.python.org/library/re.html>`__ can be used. Backslashes used to escape special characters in regular expressions must be doubled because single backslashes will be removed during query parsing. For example, to match a literal parenthesis you must enter ``\\(`` or alternatively use `super quotes` (see below). Regular expression searches are 'contains' searches unless the expression is anchored. Character variants are significant: ``~e`` doesn't match ``é``.
Regular expression searches are indicated by prefixing the search string with a tilde (~). Any `Python-compatible regular expression <https://docs.python.org/library/re.html>`__ can be used. Backslashes used to escape special characters in regular expressions must be doubled because single backslashes will be removed during query parsing. For example, to match a literal parenthesis you must enter ``\\(`` or alternatively use `super-quotes` (see below). Regular expression searches are 'contains' searches unless the expression is anchored. Character variants are significant: ``~e`` doesn't match ``é``.
*'Character variant' searches*

View File

@ -8,6 +8,7 @@ __docformat__ = 'restructuredtext en'
import json
from collections import defaultdict
from threading import Thread
from functools import partial
from qt.core import (
QApplication, QFont, QFontInfo, QFontDialog, QColorDialog, QPainter, QDialog,
@ -23,7 +24,7 @@ from calibre.ebooks.metadata.sources.prefs import msprefs
from calibre.gui2.custom_column_widgets import get_field_list as em_get_field_list
from calibre.gui2 import default_author_link, icon_resource_manager, choose_save_file, choose_files
from calibre.gui2.dialogs.template_dialog import TemplateDialog
from calibre.gui2.preferences import ConfigWidgetBase, test_widget, CommaSeparatedList
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
from calibre.gui2.preferences.look_feel_ui import Ui_Form
from calibre.gui2 import config, gprefs, qt_app, open_local_file, question_dialog, error_dialog
from calibre.utils.localization import (available_translations,
@ -377,24 +378,101 @@ class TBDisplayedFields(DisplayedFields): # {{{
pref_data_override=pref_data_override)
if use_defaults:
hc = []
self.changed = True
elif pref_data_override:
hc = [k for k,v in pref_data_override if not v]
self.changed = True
else:
hc = tv.hidden_categories
self.beginResetModel()
self.fields = [[x, x not in hc] for x in cat_ord]
self.endResetModel()
self.changed = True
def is_standard_category(self, key):
return self.gui.tags_view.model().is_standard_category(key)
def commit(self):
if self.changed:
self.db.new_api.set_pref('tag_browser_hidden_categories', [k for k,v in self.fields if not v])
self.db.new_api.set_pref('tag_browser_category_order', [k for k,v in self.fields])
self.gui.tags_view.model().set_hidden_categories({k for k,v in self.fields if not v})
self.db.prefs.set('tag_browser_hidden_categories', [k for k,v in self.fields if not v])
self.db.prefs.set('tag_browser_category_order', [k for k,v in self.fields])
self.gui.tags_view.model().reset_tag_browser_categories()
# }}}
class TBPartitionedFields(DisplayedFields): # {{{
# The code in this class depends on the fact that the tag browser is
# initialized before this class is instantiated.
def __init__(self, db, parent=None, category_icons=None):
DisplayedFields.__init__(self, db, parent, category_icons=category_icons)
from calibre.gui2.ui import get_gui
self.gui = get_gui()
def initialize(self, use_defaults=False, pref_data_override=None):
tv = self.gui.tags_view
cats = tv.model().categories
ans = []
if use_defaults:
ans = [[k, True] for k in cats.keys()]
self.changed = True
elif pref_data_override:
po = {k:v for k,v in pref_data_override}
ans = [[k, po.get(k, True)] for k in cats.keys()]
self.changed = True
else:
# Check if setting not migrated yet
cats_to_partition = self.db.prefs.get('tag_browser_dont_collapse',
gprefs.get('tag_browser_dont_collapse'))
for key in cats:
ans.append([key, not key in cats_to_partition])
self.beginResetModel()
self.fields = ans
self.endResetModel()
def commit(self):
if self.changed:
# Migrate to a per-library setting
self.db.prefs.set('tag_browser_dont_collapse', [k for k,v in self.fields if not v])
self.gui.tags_view.model().reset_tag_browser_categories()
# }}}
class TBHierarchicalFields(DisplayedFields): # {{{
# The code in this class depends on the fact that the tag browser is
# initialized before this class is instantiated.
cant_make_hierarical = {'authors', 'publisher', 'formats', 'news',
'identifiers', 'languages', 'rating'}
def __init__(self, db, parent=None, category_icons=None):
DisplayedFields.__init__(self, db, parent, category_icons=category_icons)
from calibre.gui2.ui import get_gui
self.gui = get_gui()
def initialize(self, use_defaults=False, pref_data_override=None):
tv = self.gui.tags_view
cats = [k for k in tv.model().categories.keys() if k not in self.cant_make_hierarical]
ans = []
if use_defaults:
ans = [[k, False] for k in cats]
self.changed = True
elif pref_data_override:
ph = {k:v for k,v in pref_data_override}
ans = [[k, ph.get(k, False)] for k in cats]
self.changed = True
else:
hier_cats = self.db.prefs.get('categories_using_hierarchy')
for key in cats:
ans.append([key, key in hier_cats])
self.beginResetModel()
self.fields = ans
self.endResetModel()
def commit(self):
if self.changed:
self.db.prefs.set('categories_using_hierarchy', [k for k,v in self.fields if v])
self.gui.tags_view.model().reset_tag_browser_categories()
# }}}
@ -547,20 +625,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
r('tags_browser_collapse_at', gprefs)
r('tags_browser_collapse_fl_at', gprefs)
choices = {k for k in db.field_metadata.all_field_keys()
if (db.field_metadata[k]['is_category'] and (
db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration'
]) and not db.field_metadata[k]['display'].get('is_names', False)) or (
db.field_metadata[k]['datatype'] in ['composite'
] and db.field_metadata[k]['display'].get('make_category', False))}
choices |= {'search'}
r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList,
choices=sorted(choices, key=sort_key))
choices -= {'authors', 'publisher', 'formats', 'news', 'identifiers'}
r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
choices=sorted(choices, key=sort_key))
fm = db.field_metadata
choices = sorted(((fm[k]['name'], k) for k in fm.displayable_field_keys() if fm[k]['name']),
key=lambda x:sort_key(x[0]))
@ -601,9 +665,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
lambda self: move_field_up(self.em_display_order, self.em_display_model))
connect_lambda(self.em_down_button.clicked, self,
lambda self: move_field_down(self.em_display_order, self.em_display_model))
self.em_export_layout_button.clicked.connect(self.em_export_layout)
self.em_import_layout_button.clicked.connect(self.em_import_layout)
self.em_reset_layout_button.clicked.connect(self.em_reset_layout)
self.em_export_layout_button.clicked.connect(partial(self.export_layout,
model=self.em_display_model))
self.em_import_layout_button.clicked.connect(partial(self.import_layout,
model=self.em_display_model))
self.em_reset_layout_button.clicked.connect(partial(self.reset_layout,
model=self.em_display_model))
self.qv_display_model = QVDisplayedFields(self.gui.current_db,
self.qv_display_order)
@ -619,12 +686,39 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
category_icons=self.gui.tags_view.model().category_custom_icons)
self.tb_display_model.dataChanged.connect(self.changed_signal)
self.tb_display_order.setModel(self.tb_display_model)
self.tb_reset_layout_button.clicked.connect(self.tb_reset_layout)
self.tb_export_layout_button.clicked.connect(self.tb_export_layout)
self.tb_import_layout_button.clicked.connect(self.tb_import_layout)
self.tb_reset_layout_button.clicked.connect(partial(self.reset_layout,
model=self.tb_display_model))
self.tb_export_layout_button.clicked.connect(partial(self.export_layout,
model=self.tb_display_model))
self.tb_import_layout_button.clicked.connect(partial(self.import_layout,
model=self.tb_display_model))
self.tb_up_button.clicked.connect(self.tb_up_button_clicked)
self.tb_down_button.clicked.connect(self.tb_down_button_clicked)
self.tb_categories_to_part_model = TBPartitionedFields(self.gui.current_db,
self.tb_cats_to_partition,
category_icons=self.gui.tags_view.model().category_custom_icons)
self.tb_categories_to_part_model.dataChanged.connect(self.changed_signal)
self.tb_cats_to_partition.setModel(self.tb_categories_to_part_model)
self.tb_partition_reset_button.clicked.connect(partial(self.reset_layout,
model=self.tb_categories_to_part_model))
self.tb_partition_export_layout_button.clicked.connect(partial(self.export_layout,
model=self.tb_categories_to_part_model))
self.tb_partition_import_layout_button.clicked.connect(partial(self.import_layout,
model=self.tb_categories_to_part_model))
self.tb_hierarchical_cats_model = TBHierarchicalFields(self.gui.current_db,
self.tb_hierarchical_cats,
category_icons=self.gui.tags_view.model().category_custom_icons)
self.tb_hierarchical_cats_model.dataChanged.connect(self.changed_signal)
self.tb_hierarchical_cats.setModel(self.tb_hierarchical_cats_model)
self.tb_hierarchy_reset_layout_button.clicked.connect(partial(self.reset_layout,
model=self.tb_hierarchical_cats_model))
self.tb_hierarchy_export_layout_button.clicked.connect(partial(self.export_layout,
model=self.tb_hierarchical_cats_model))
self.tb_hierarchy_import_layout_button.clicked.connect(partial(self.import_layout,
model=self.tb_hierarchical_cats_model))
self.edit_rules = EditRules(self.tabWidget)
self.edit_rules.changed.connect(self.changed_signal)
self.tabWidget.addTab(self.edit_rules,
@ -695,19 +789,19 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.opt_color_palette.setEnabled(enabled)
self.opt_color_palette_label.setEnabled(enabled)
def em_export_layout(self):
def export_layout(self, model=None):
filename = choose_save_file(self, 'em_import_export_field_list',
_('Save column list to file'),
filters=[(_('Column list'), ['json'])])
if filename:
try:
with open(filename, 'w') as f:
json.dump(self.em_display_model.fields, f, indent=1)
json.dump(model.fields, f, indent=1)
except Exception as err:
error_dialog(self, _('Export field layout'),
_('<p>Could not write field list. Error:<br>%s')%err, show=True)
def em_import_layout(self):
def import_layout(self, model=None):
filename = choose_files(self, 'em_import_export_field_list',
_('Load column list from file'),
filters=[(_('Column list'), ['json'])])
@ -715,44 +809,14 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
try:
with open(filename[0]) as f:
fields = json.load(f)
self.em_display_model.initialize(pref_data_override=fields)
model.initialize(pref_data_override=fields)
self.changed_signal.emit()
except Exception as err:
error_dialog(self, _('Import layout'),
_('<p>Could not read field list. Error:<br>%s')%err, show=True)
def em_reset_layout(self):
self.em_display_model.initialize(use_defaults=True)
self.changed_signal.emit()
def tb_export_layout(self):
filename = choose_save_file(self, 'em_import_export_field_list',
_('Save column list to file'),
filters=[(_('Column list'), ['json'])])
if filename:
try:
with open(filename, 'w') as f:
json.dump(self.tb_display_model.fields, f, indent=1)
except Exception as err:
error_dialog(self, _('Export field layout'),
_('<p>Could not write field list. Error:<br>%s')%err, show=True)
def tb_import_layout(self):
filename = choose_files(self, 'em_import_export_field_list',
_('Load column list from file'),
filters=[(_('Column list'), ['json'])])
if filename:
try:
with open(filename[0]) as f:
fields = json.load(f)
self.tb_display_model.initialize(pref_data_override=fields)
self.changed_signal.emit()
except Exception as err:
error_dialog(self, _('Import layout'),
_('<p>Could not read field list. Error:<br>%s')%err, show=True)
def tb_reset_layout(self):
self.tb_display_model.initialize(use_defaults=True)
def reset_layout(self, model=None):
model.initialize(use_defaults=True)
self.changed_signal.emit()
def tb_down_button_clicked(self):
@ -839,6 +903,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.em_display_model.initialize()
self.qv_display_model.initialize()
self.tb_display_model.initialize()
self.tb_categories_to_part_model.initialize()
self.tb_hierarchical_cats_model.initialize()
db = self.gui.current_db
mi = []
try:
@ -974,6 +1040,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.em_display_model.commit()
self.qv_display_model.commit()
self.tb_display_model.commit()
self.tb_categories_to_part_model.commit()
self.tb_hierarchical_cats_model.commit()
self.edit_rules.commit(self.gui.current_db.prefs)
self.icon_rules.commit(self.gui.current_db.prefs)
self.grid_rules.commit(self.gui.current_db.prefs)

View File

@ -1156,17 +1156,10 @@ using the Tab key. The F2 (Edit) key will still open the template editor.&lt;/p&
<string>Select the categories to display in the Tag browser and their order</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>User categories and Saved searches cannot be moved</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QToolButton" name="tb_down_button">
<property name="toolTip">
<string>Move down</string>
<string>Move down. User categories and Saved searches cannot be moved</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
@ -1177,7 +1170,7 @@ using the Tab key. The F2 (Edit) key will still open the template editor.&lt;/p&
<item row="2" column="1">
<widget class="QToolButton" name="tb_up_button">
<property name="toolTip">
<string>Move up</string>
<string>Move up. User categories and Saved searches cannot be moved</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
@ -1269,6 +1262,8 @@ structure and you want to use the same column order for each one.&lt;/p&gt;</str
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="0">
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
@ -1295,49 +1290,6 @@ if you never want subcategories</string>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Co&amp;llapse when more items than:</string>
</property>
<property name="buddy">
<cstring>opt_tags_browser_collapse_at</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="opt_tags_browser_collapse_at">
<property name="toolTip">
<string>If a Tag browser category has more than this number of items, it is divided
up into subcategories. If the partition method is set to disable, this value is ignored.</string>
</property>
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Combine letters &amp;when fewer items than:</string>
</property>
<property name="buddy">
<cstring>opt_tags_browser_collapse_fl_at</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="opt_tags_browser_collapse_fl_at">
<property name="toolTip">
<string>If collapsing by first letter, combine adjacent letters together if
there are fewer items under a letter than specified here. If the partition method is
not set to first letter, this value is ignored. Set to zero to disable.</string>
</property>
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Spacing between &amp;items:</string>
@ -1347,7 +1299,7 @@ not set to first letter, this value is ignored. Set to zero to disable.</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="opt_tag_browser_item_padding">
<property name="toolTip">
<string>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. </string>
@ -1369,66 +1321,220 @@ not set to first letter, this value is ignored. Set to zero to disable.</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_8111">
</layout>
</item>
<item row="0" column="1">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Categories &amp;not to partition:</string>
<string>Combine letters &amp;when fewer items than:</string>
</property>
<property name="buddy">
<cstring>opt_tag_browser_dont_collapse</cstring>
<cstring>opt_tags_browser_collapse_fl_at</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="EditWithComplete" name="opt_tag_browser_dont_collapse">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item row="0" column="1">
<widget class="QSpinBox" name="opt_tags_browser_collapse_fl_at">
<property name="toolTip">
<string>A comma-separated list of categories that are not to
be partitioned even if the number of items is larger than
the value shown above. This option can be used to
avoid collapsing hierarchical categories that have only
a few top-level elements.</string>
<string>If collapsing by first letter, combine adjacent letters together if
there are fewer items under a letter than specified here. If the partition method is
not set to first letter, this value is ignored. Set to zero to disable.</string>
</property>
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_81">
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>C&amp;ategories with hierarchical items:</string>
<string>Co&amp;llapse when more items than:</string>
</property>
<property name="buddy">
<cstring>opt_categories_using_hierarchy</cstring>
<cstring>opt_tags_browser_collapse_at</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="EditWithComplete" name="opt_categories_using_hierarchy">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item row="1" column="1">
<widget class="QSpinBox" name="opt_tags_browser_collapse_at">
<property name="toolTip">
<string>A comma-separated list of categories in which items containing
periods are displayed in the Tag browser trees. For example, if
this box contains 'tags' then tags of the form 'Mystery.English'
and 'Mystery.Thriller' will be displayed with English and Thriller
both under 'Mystery'. If 'tags' is not in this box,
then the tags will be displayed each on their own line.</string>
<string>If a Tag browser category has more than this number of items, it is divided
up into subcategories. If the partition method is set to disable, this value is ignored.</string>
</property>
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel">
<property name="text">
<string>Select categories to &amp;partition:</string>
</property>
<property name="buddy">
<cstring>tb_cats_to_partition</cstring>
</property>
<property name="toolTip">
<string>&lt;p&gt;Check the box for categories that are to
be partitioned using the criteria above. Uncheck the box if you don't want to
partition a category even if the number of items is larger than
the value shown above. This option can be used to
avoid collapsing hierarchical categories that have only
a few top-level elements.&lt;/p&gt;</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QListView" name="tb_cats_to_partition">
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_41">
<item>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="0">
<widget class="QPushButton" name="tb_partition_reset_button">
<property name="toolTip">
<string>&lt;p&gt;Click this button to reset the list to its default order.&lt;/p&gt;</string>
</property>
<property name="text">
<string>Reset list</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="tb_partition_import_layout_button">
<property name="toolTip">
<string>&lt;p&gt;Click this button to set the list to one
previously exported. This could be useful if you have several libraries with
similar structure and you want to use the same for each one.&lt;/p&gt;</string>
</property>
<property name="text">
<string>Import list</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="tb_partition_export_layout_button">
<property name="toolTip">
<string>&lt;p&gt;Click this button to write the current display
settings to a file. This could be useful if you have several libraries with similar
structure and you want to use the same for each one.&lt;/p&gt;</string>
</property>
<property name="text">
<string>Export list</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="1">
<widget class="QLabel">
<property name="text">
<string>Select categories with &amp;hierarchical items:</string>
</property>
<property name="buddy">
<cstring>tb_hierarchical_cats</cstring>
</property>
<property name="toolTip">
<string>&lt;p&gt;Check the box for an item if it is to be displayed as a
hierarchical tree in the Tag browser. For example, if you check
'tags' then tags of the form 'Mystery.English'
and 'Mystery.Thriller' will be displayed with English and Thriller
both under 'Mystery'. If 'tags' is not checked
then the tags will be displayed each on their own line.&lt;/p&gt;</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QListView" name="tb_hierarchical_cats">
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="tb_hierarchy_reset_layout_button">
<property name="toolTip">
<string>&lt;p&gt;Click this button to reset the list to its default order.&lt;/p&gt;</string>
</property>
<property name="text">
<string>Reset list</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="tb_hierarchy_import_layout_button">
<property name="toolTip">
<string>&lt;p&gt;Click this button to set the list to one
previously exported. This could be useful if you have several libraries with
similar structure and you want to use the same for each one.&lt;/p&gt;</string>
</property>
<property name="text">
<string>Import list</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="tb_hierarchy_export_layout_button">
<property name="toolTip">
<string>&lt;p&gt;Click this button to write the current display
settings to a file. This could be useful if you have several libraries with similar
structure and you want to use the same for each one.&lt;/p&gt;</string>
</property>
<property name="text">
<string>Export list</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="opt_show_avg_rating">
<property name="text">
<string>Show &amp;average ratings</string>
@ -1438,14 +1544,14 @@ then the tags will be displayed each on their own line.</string>
</property>
</widget>
</item>
<item row="0" column="1">
<item row="5" column="1">
<widget class="QCheckBox" name="opt_tag_browser_show_tooltips">
<property name="text">
<string>Show &amp;tooltips</string>
</property>
</widget>
</item>
<item row="1" column="0">
<item row="6" column="0">
<widget class="QCheckBox" name="opt_tag_browser_show_counts">
<property name="toolTip">
<string>Show counts for items in the Tag browser. Such as the number of books
@ -1457,14 +1563,14 @@ see the counts by hovering your mouse over any item.</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="6" column="1">
<widget class="QCheckBox" name="opt_tag_browser_old_look">
<property name="text">
<string>Use &amp;alternating row colors</string>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="7" column="0">
<widget class="QCheckBox" name="opt_tag_browser_hide_empty_categories">
<property name="toolTip">
<string>When checked, calibre will automatically hide any category
@ -1477,7 +1583,7 @@ see the counts by hovering your mouse over any item.</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="7" column="1">
<widget class="QCheckBox" name="opt_tag_browser_always_autocollapse">
<property name="toolTip">
<string>When checked, Find in the Tag browser will show all items
@ -1489,7 +1595,7 @@ see the counts by hovering your mouse over any item.</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="8" column="0" colspan="2">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="opt_tag_browser_allow_keyboard_focus">

View File

@ -402,9 +402,14 @@ class TagsModel(QAbstractItemModel): # {{{
self._run_rebuild()
self.endResetModel()
def set_hidden_categories(self, cats):
def reset_tag_browser_categories(self):
self.beginResetModel()
self.hidden_categories = cats
hidden_cats = self.db.new_api.pref('tag_browser_hidden_categories', {})
self.hidden_categories = set()
# strip out any non-existent field keys
for cat in hidden_cats:
if cat in self.db.field_metadata:
self.hidden_categories.add(cat)
self._run_rebuild()
self.endResetModel()
@ -541,7 +546,9 @@ class TagsModel(QAbstractItemModel): # {{{
is_gst = category.is_gst
if key not in data:
return
if key in self.prefs['tag_browser_dont_collapse']:
# Use old pref if new one doesn't exist
if key in self.db.prefs.get('tag_browser_dont_collapse',
self.prefs['tag_browser_dont_collapse']):
collapse_model = 'disable'
cat_len = len(data[key])
if cat_len <= 0: