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*
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* *'Character variant' searches*

View File

@ -8,6 +8,7 @@ __docformat__ = 'restructuredtext en'
import json import json
from collections import defaultdict from collections import defaultdict
from threading import Thread from threading import Thread
from functools import partial
from qt.core import ( from qt.core import (
QApplication, QFont, QFontInfo, QFontDialog, QColorDialog, QPainter, QDialog, 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.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 import default_author_link, icon_resource_manager, choose_save_file, choose_files
from calibre.gui2.dialogs.template_dialog import TemplateDialog 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.preferences.look_feel_ui import Ui_Form
from calibre.gui2 import config, gprefs, qt_app, open_local_file, question_dialog, error_dialog from calibre.gui2 import config, gprefs, qt_app, open_local_file, question_dialog, error_dialog
from calibre.utils.localization import (available_translations, from calibre.utils.localization import (available_translations,
@ -377,24 +378,101 @@ class TBDisplayedFields(DisplayedFields): # {{{
pref_data_override=pref_data_override) pref_data_override=pref_data_override)
if use_defaults: if use_defaults:
hc = [] hc = []
self.changed = True
elif pref_data_override: elif pref_data_override:
hc = [k for k,v in pref_data_override if not v] hc = [k for k,v in pref_data_override if not v]
self.changed = True
else: else:
hc = tv.hidden_categories hc = tv.hidden_categories
self.beginResetModel() self.beginResetModel()
self.fields = [[x, x not in hc] for x in cat_ord] self.fields = [[x, x not in hc] for x in cat_ord]
self.endResetModel() self.endResetModel()
self.changed = True
def is_standard_category(self, key): def is_standard_category(self, key):
return self.gui.tags_view.model().is_standard_category(key) return self.gui.tags_view.model().is_standard_category(key)
def commit(self): def commit(self):
if self.changed: 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.prefs.set('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.db.prefs.set('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.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_at', gprefs)
r('tags_browser_collapse_fl_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 fm = db.field_metadata
choices = sorted(((fm[k]['name'], k) for k in fm.displayable_field_keys() if fm[k]['name']), choices = sorted(((fm[k]['name'], k) for k in fm.displayable_field_keys() if fm[k]['name']),
key=lambda x:sort_key(x[0])) 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)) lambda self: move_field_up(self.em_display_order, self.em_display_model))
connect_lambda(self.em_down_button.clicked, self, connect_lambda(self.em_down_button.clicked, self,
lambda self: move_field_down(self.em_display_order, self.em_display_model)) 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_export_layout_button.clicked.connect(partial(self.export_layout,
self.em_import_layout_button.clicked.connect(self.em_import_layout) model=self.em_display_model))
self.em_reset_layout_button.clicked.connect(self.em_reset_layout) 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_model = QVDisplayedFields(self.gui.current_db,
self.qv_display_order) self.qv_display_order)
@ -615,16 +682,43 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
lambda self: move_field_down(self.qv_display_order, self.qv_display_model)) lambda self: move_field_down(self.qv_display_order, self.qv_display_model))
self.tb_display_model = TBDisplayedFields(self.gui.current_db, self.tb_display_model = TBDisplayedFields(self.gui.current_db,
self.tb_display_order, self.tb_display_order,
category_icons=self.gui.tags_view.model().category_custom_icons) category_icons=self.gui.tags_view.model().category_custom_icons)
self.tb_display_model.dataChanged.connect(self.changed_signal) self.tb_display_model.dataChanged.connect(self.changed_signal)
self.tb_display_order.setModel(self.tb_display_model) self.tb_display_order.setModel(self.tb_display_model)
self.tb_reset_layout_button.clicked.connect(self.tb_reset_layout) self.tb_reset_layout_button.clicked.connect(partial(self.reset_layout,
self.tb_export_layout_button.clicked.connect(self.tb_export_layout) model=self.tb_display_model))
self.tb_import_layout_button.clicked.connect(self.tb_import_layout) 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_up_button.clicked.connect(self.tb_up_button_clicked)
self.tb_down_button.clicked.connect(self.tb_down_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 = EditRules(self.tabWidget)
self.edit_rules.changed.connect(self.changed_signal) self.edit_rules.changed.connect(self.changed_signal)
self.tabWidget.addTab(self.edit_rules, 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.setEnabled(enabled)
self.opt_color_palette_label.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', filename = choose_save_file(self, 'em_import_export_field_list',
_('Save column list to file'), _('Save column list to file'),
filters=[(_('Column list'), ['json'])]) filters=[(_('Column list'), ['json'])])
if filename: if filename:
try: try:
with open(filename, 'w') as f: 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: except Exception as err:
error_dialog(self, _('Export field layout'), error_dialog(self, _('Export field layout'),
_('<p>Could not write field list. Error:<br>%s')%err, show=True) _('<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', filename = choose_files(self, 'em_import_export_field_list',
_('Load column list from file'), _('Load column list from file'),
filters=[(_('Column list'), ['json'])]) filters=[(_('Column list'), ['json'])])
@ -715,44 +809,14 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
try: try:
with open(filename[0]) as f: with open(filename[0]) as f:
fields = json.load(f) fields = json.load(f)
self.em_display_model.initialize(pref_data_override=fields) model.initialize(pref_data_override=fields)
self.changed_signal.emit() self.changed_signal.emit()
except Exception as err: except Exception as err:
error_dialog(self, _('Import layout'), error_dialog(self, _('Import layout'),
_('<p>Could not read field list. Error:<br>%s')%err, show=True) _('<p>Could not read field list. Error:<br>%s')%err, show=True)
def em_reset_layout(self): def reset_layout(self, model=None):
self.em_display_model.initialize(use_defaults=True) 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)
self.changed_signal.emit() self.changed_signal.emit()
def tb_down_button_clicked(self): def tb_down_button_clicked(self):
@ -839,6 +903,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.em_display_model.initialize() self.em_display_model.initialize()
self.qv_display_model.initialize() self.qv_display_model.initialize()
self.tb_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 db = self.gui.current_db
mi = [] mi = []
try: try:
@ -974,6 +1040,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.em_display_model.commit() self.em_display_model.commit()
self.qv_display_model.commit() self.qv_display_model.commit()
self.tb_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.edit_rules.commit(self.gui.current_db.prefs)
self.icon_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) 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> <string>Select the categories to display in the Tag browser and their order</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <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"> <item row="4" column="1">
<widget class="QToolButton" name="tb_down_button"> <widget class="QToolButton" name="tb_down_button">
<property name="toolTip"> <property name="toolTip">
<string>Move down</string> <string>Move down. User categories and Saved searches cannot be moved</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../../../resources/images.qrc"> <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"> <item row="2" column="1">
<widget class="QToolButton" name="tb_up_button"> <widget class="QToolButton" name="tb_up_button">
<property name="toolTip"> <property name="toolTip">
<string>Move up</string> <string>Move up. User categories and Saved searches cannot be moved</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../../../resources/images.qrc"> <iconset resource="../../../../resources/images.qrc">
@ -1269,166 +1262,279 @@ structure and you want to use the same column order for each one.&lt;/p&gt;</str
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QFormLayout" name="formLayout"> <layout class="QGridLayout" name="gridLayout_10">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_9"> <layout class="QFormLayout" name="formLayout">
<property name="text"> <property name="fieldGrowthPolicy">
<string>&amp;Category partitioning method:</string> <enum>QFormLayout::ExpandingFieldsGrow</enum>
</property> </property>
<property name="buddy"> <item row="0" column="0">
<cstring>opt_tags_browser_partition_method</cstring> <widget class="QLabel" name="label_9">
</property> <property name="text">
</widget> <string>&amp;Category partitioning method:</string>
</item> </property>
<item row="0" column="1"> <property name="buddy">
<widget class="QComboBox" name="opt_tags_browser_partition_method"> <cstring>opt_tags_browser_partition_method</cstring>
<property name="toolTip"> </property>
<string>Choose how Tag browser subcategories are displayed when </widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="opt_tags_browser_partition_method">
<property name="toolTip">
<string>Choose how Tag browser subcategories are displayed when
there are more items than the limit. Select by first there are more items than the limit. Select by first
letter to see an A, B, C list. Choose partitioned to letter to see an A, B, C list. Choose partitioned to
have a list of fixed-sized groups. Set to disabled have a list of fixed-sized groups. Set to disabled
if you never want subcategories</string> if you never want subcategories</string>
</property> </property>
</widget> </widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Spacing between &amp;items:</string>
</property>
<property name="buddy">
<cstring>opt_tag_browser_item_padding</cstring>
</property>
</widget>
</item>
<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>
</property>
<property name="suffix">
<string> ex</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-1.000000000000000</double>
</property>
<property name="maximum">
<double>2.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
</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>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="0" 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="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>
</layout>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_10"> <widget class="QLabel">
<property name="text"> <property name="text">
<string>Co&amp;llapse when more items than:</string> <string>Select categories to &amp;partition:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>opt_tags_browser_collapse_at</cstring> <cstring>tb_cats_to_partition</cstring>
</property> </property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="opt_tags_browser_collapse_at">
<property name="toolTip"> <property name="toolTip">
<string>If a Tag browser category has more than this number of items, it is divided <string>&lt;p&gt;Check the box for categories that are to
up into subcategories. If the partition method is set to disable, this value is ignored.</string> be partitioned using the criteria above. Uncheck the box if you don't want to
</property> partition a category even if the number of items is larger than
<property name="maximum"> the value shown above. This option can be used to
<number>10000</number> avoid collapsing hierarchical categories that have only
a few top-level elements.&lt;/p&gt;</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_10"> <widget class="QListView" name="tb_cats_to_partition">
<property name="text"> <property name="minimumSize">
<string>Combine letters &amp;when fewer items than:</string> <size>
<width>0</width>
<height>200</height>
</size>
</property> </property>
<property name="buddy"> <property name="alternatingRowColors">
<cstring>opt_tags_browser_collapse_fl_at</cstring> <bool>true</bool>
</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> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label"> <layout class="QHBoxLayout" name="horizontalLayout_41">
<item>
<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"> <property name="text">
<string>Spacing between &amp;items:</string> <string>Select categories with &amp;hierarchical items:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>opt_tag_browser_item_padding</cstring> <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> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="3" column="1">
<widget class="QDoubleSpinBox" name="opt_tag_browser_item_padding"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="toolTip"> <item>
<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> <widget class="QPushButton" name="tb_hierarchy_reset_layout_button">
</property> <property name="toolTip">
<property name="suffix"> <string>&lt;p&gt;Click this button to reset the list to its default order.&lt;/p&gt;</string>
<string> ex</string> </property>
</property> <property name="text">
<property name="decimals"> <string>Reset list</string>
<number>1</number> </property>
</property> </widget>
<property name="minimum"> </item>
<double>-1.000000000000000</double> <item>
</property> <widget class="QPushButton" name="tb_hierarchy_import_layout_button">
<property name="maximum"> <property name="toolTip">
<double>2.000000000000000</double> <string>&lt;p&gt;Click this button to set the list to one
</property> previously exported. This could be useful if you have several libraries with
<property name="singleStep"> similar structure and you want to use the same for each one.&lt;/p&gt;</string>
<double>0.100000000000000</double> </property>
</property> <property name="text">
</widget> <string>Import list</string>
</item> </property>
<item row="4" column="0"> </widget>
<widget class="QLabel" name="label_8111"> </item>
<property name="text"> <item>
<string>Categories &amp;not to partition:</string> <widget class="QPushButton" name="tb_hierarchy_export_layout_button">
</property> <property name="toolTip">
<property name="buddy"> <string>&lt;p&gt;Click this button to write the current display
<cstring>opt_tag_browser_dont_collapse</cstring> settings to a file. This could be useful if you have several libraries with similar
</property> structure and you want to use the same for each one.&lt;/p&gt;</string>
</widget> </property>
</item> <property name="text">
<item row="4" column="1"> <string>Export list</string>
<widget class="EditWithComplete" name="opt_tag_browser_dont_collapse"> </property>
<property name="sizePolicy"> </widget>
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> </item>
<horstretch>0</horstretch> <item>
<verstretch>0</verstretch> <spacer name="horizontalSpacer">
</sizepolicy> <property name="orientation">
</property> <enum>Qt::Horizontal</enum>
<property name="toolTip"> </property>
<string>A comma-separated list of categories that are not to <property name="sizeHint" stdset="0">
be partitioned even if the number of items is larger than <size>
the value shown above. This option can be used to <width>40</width>
avoid collapsing hierarchical categories that have only <height>20</height>
a few top-level elements.</string> </size>
</property> </property>
</widget> </spacer>
</item>
</layout>
</item> </item>
<item row="5" column="0"> <item row="5" column="0">
<widget class="QLabel" name="label_81">
<property name="text">
<string>C&amp;ategories with hierarchical items:</string>
</property>
<property name="buddy">
<cstring>opt_categories_using_hierarchy</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>
<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>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="0">
<widget class="QCheckBox" name="opt_show_avg_rating"> <widget class="QCheckBox" name="opt_show_avg_rating">
<property name="text"> <property name="text">
<string>Show &amp;average ratings</string> <string>Show &amp;average ratings</string>
@ -1438,14 +1544,14 @@ then the tags will be displayed each on their own line.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="5" column="1">
<widget class="QCheckBox" name="opt_tag_browser_show_tooltips"> <widget class="QCheckBox" name="opt_tag_browser_show_tooltips">
<property name="text"> <property name="text">
<string>Show &amp;tooltips</string> <string>Show &amp;tooltips</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="6" column="0">
<widget class="QCheckBox" name="opt_tag_browser_show_counts"> <widget class="QCheckBox" name="opt_tag_browser_show_counts">
<property name="toolTip"> <property name="toolTip">
<string>Show counts for items in the Tag browser. Such as the number of books <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> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="6" column="1">
<widget class="QCheckBox" name="opt_tag_browser_old_look"> <widget class="QCheckBox" name="opt_tag_browser_old_look">
<property name="text"> <property name="text">
<string>Use &amp;alternating row colors</string> <string>Use &amp;alternating row colors</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="7" column="0">
<widget class="QCheckBox" name="opt_tag_browser_hide_empty_categories"> <widget class="QCheckBox" name="opt_tag_browser_hide_empty_categories">
<property name="toolTip"> <property name="toolTip">
<string>When checked, calibre will automatically hide any category <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> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="7" column="1">
<widget class="QCheckBox" name="opt_tag_browser_always_autocollapse"> <widget class="QCheckBox" name="opt_tag_browser_always_autocollapse">
<property name="toolTip"> <property name="toolTip">
<string>When checked, Find in the Tag browser will show all items <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> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2"> <item row="8" column="0" colspan="2">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QCheckBox" name="opt_tag_browser_allow_keyboard_focus"> <widget class="QCheckBox" name="opt_tag_browser_allow_keyboard_focus">

View File

@ -402,9 +402,14 @@ class TagsModel(QAbstractItemModel): # {{{
self._run_rebuild() self._run_rebuild()
self.endResetModel() self.endResetModel()
def set_hidden_categories(self, cats): def reset_tag_browser_categories(self):
self.beginResetModel() 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._run_rebuild()
self.endResetModel() self.endResetModel()
@ -541,7 +546,9 @@ class TagsModel(QAbstractItemModel): # {{{
is_gst = category.is_gst is_gst = category.is_gst
if key not in data: if key not in data:
return 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' collapse_model = 'disable'
cat_len = len(data[key]) cat_len = len(data[key])
if cat_len <= 0: if cat_len <= 0: