Merge branch 'master' of https://github.com/cbhaley/calibre into master

This commit is contained in:
Kovid Goyal 2020-10-14 20:58:16 +05:30
commit dc67ed88f2
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 88 additions and 5 deletions

View File

@ -134,6 +134,7 @@ def create_defs():
defs['font'] = None defs['font'] = None
defs['tags_browser_partition_method'] = 'first letter' defs['tags_browser_partition_method'] = 'first letter'
defs['tags_browser_collapse_at'] = 100 defs['tags_browser_collapse_at'] = 100
defs['tags_browser_collapse_fl_at'] = 0
defs['tag_browser_dont_collapse'] = [] defs['tag_browser_dont_collapse'] = []
defs['edit_metadata_single_layout'] = 'default' defs['edit_metadata_single_layout'] = 'default'
defs['preserve_date_on_ctl'] = True defs['preserve_date_on_ctl'] = True

View File

@ -487,6 +487,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
(_('Partitioned'), 'partition')] (_('Partitioned'), 'partition')]
r('tags_browser_partition_method', gprefs, choices=choices) r('tags_browser_partition_method', gprefs, choices=choices)
r('tags_browser_collapse_at', gprefs) r('tags_browser_collapse_at', gprefs)
r('tags_browser_collapse_fl_at', gprefs)
r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList) r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)
choices = {k for k in db.field_metadata.all_field_keys() choices = {k for k in db.field_metadata.all_field_keys()

View File

@ -914,7 +914,32 @@ up into subcategories. If the partition method is set to disable, this value is
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="4" 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="4" 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.</string>
<property name="minimum">
<number>1</number>
</property>
</property>
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_8111"> <widget class="QLabel" name="label_8111">
<property name="text"> <property name="text">
<string>Categories &amp;not to partition:</string> <string>Categories &amp;not to partition:</string>
@ -924,7 +949,7 @@ up into subcategories. If the partition method is set to disable, this value is
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="6" column="1">
<widget class="EditWithComplete" name="opt_tag_browser_dont_collapse"> <widget class="EditWithComplete" name="opt_tag_browser_dont_collapse">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1044,7 +1069,7 @@ see the counts by hovering your mouse over any item.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="5" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Spacing between &amp;items:</string> <string>Spacing between &amp;items:</string>
@ -1054,7 +1079,7 @@ see the counts by hovering your mouse over any item.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="5" column="1">
<widget class="QDoubleSpinBox" name="opt_tag_browser_item_padding"> <widget class="QDoubleSpinBox" name="opt_tag_browser_item_padding">
<property name="toolTip"> <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> <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>

View File

@ -7,7 +7,7 @@ __copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import traceback, copy, os import traceback, copy, os
from collections import OrderedDict from collections import OrderedDict, namedtuple
from PyQt5.Qt import (QAbstractItemModel, QIcon, QFont, Qt, from PyQt5.Qt import (QAbstractItemModel, QIcon, QFont, Qt,
QMimeData, QModelIndex, pyqtSignal, QObject) QMimeData, QModelIndex, pyqtSignal, QObject)
@ -290,6 +290,8 @@ class TagTreeItem(object): # {{{
# }}} # }}}
FL_Interval = namedtuple('FL_Interval', ['first_chr', 'last_chr', 'length'])
class TagsModel(QAbstractItemModel): # {{{ class TagsModel(QAbstractItemModel): # {{{
search_item_renamed = pyqtSignal() search_item_renamed = pyqtSignal()
@ -525,18 +527,72 @@ class TagsModel(QAbstractItemModel): # {{{
# Build a list of 'equal' first letters by noticing changes # Build a list of 'equal' first letters by noticing changes
# in ICU's 'ordinal' for the first letter. In this case, the # in ICU's 'ordinal' for the first letter. In this case, the
# first letter can actually be more than one letter long. # first letter can actually be more than one letter long.
fl_collapse_when = self.prefs['tags_browser_collapse_fl_at']
fl_collapse = True if fl_collapse_when > 1 else False
intervals = list()
cl_list = [None] * len(data[key]) cl_list = [None] * len(data[key])
last_ordnum = 0 last_ordnum = 0
last_c = ' ' last_c = ' '
last_idx = 0
for idx,tag in enumerate(data[key]): for idx,tag in enumerate(data[key]):
# Deal with items that don't have sorts, such as formats # Deal with items that don't have sorts, such as formats
t = tag.sort if tag.sort else tag.name t = tag.sort if tag.sort else tag.name
c = icu_upper(t) if t else ' ' c = icu_upper(t) if t else ' '
ordnum, ordlen = collation_order(c) ordnum, ordlen = collation_order(c)
if last_ordnum != ordnum: if last_ordnum != ordnum:
if fl_collapse and idx > 0:
intervals.append(FL_Interval(last_c, last_c, idx-last_idx))
last_idx = idx
last_c = c[0:ordlen] last_c = c[0:ordlen]
last_ordnum = ordnum last_ordnum = ordnum
cl_list[idx] = last_c cl_list[idx] = last_c
if fl_collapse:
intervals.append(FL_Interval(last_c, last_c, len(cl_list)-last_idx))
# Combine together first letter categories that are smaller
# than the specified option. We choose which item to combine
# by the size of the items before and after, privileging making
# smaller categories. Loop through the intervals doing the combine
# until nothing changes. Multiple iterations are required because
# we might need to combine categories that are already combined.
fl_intervals_changed = True
null_interval = FL_Interval('', '', 100000000)
while fl_intervals_changed and len(intervals) > 1:
fl_intervals_changed = False
for idx,interval in enumerate(intervals):
if interval.length >= fl_collapse_when:
continue
prev = next_ = null_interval
if idx == 0:
next_ = intervals[idx+1]
else:
prev = intervals[idx-1]
if idx < len(intervals) - 1:
next_ = intervals[idx+1]
if prev.length < next_.length:
intervals[idx-1] = FL_Interval(prev.first_chr,
interval.last_chr,
prev.length + interval.length)
else:
intervals[idx+1] = FL_Interval(interval.first_chr,
next_.last_chr,
next_.length + interval.length)
del intervals[idx]
fl_intervals_changed = True
break
# Now correct the first letter list, entering either the letter
# or the range for each item in the category. If we ended up
# with only one 'first letter' category then don't combine
# letters and revert to basic 'by first letter'
if len(intervals) > 1:
cur_idx = 0
for interval in intervals:
first_chr, last_chr, length = interval
for i in range(0, length):
if first_chr == last_chr:
cl_list[cur_idx] = first_chr
else:
cl_list[cur_idx] = '{0} - {1}'.format(first_chr, last_chr)
cur_idx += 1
top_level_component = 'z' + data[key][0].original_name top_level_component = 'z' + data[key][0].original_name
last_idx = -collapse last_idx = -collapse