mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
Enhancement: in book details, allow displaying is_multiple categories on separate lines.
Bug fix: is_multiple composite columns incorrectly depended on a space after the comma.
This commit is contained in:
parent
a6dc4bc09a
commit
8ad1087fd4
@ -89,7 +89,7 @@ def mi_to_html(
|
|||||||
mi,
|
mi,
|
||||||
field_list=None, default_author_link=None, use_roman_numbers=True,
|
field_list=None, default_author_link=None, use_roman_numbers=True,
|
||||||
rating_font='Liberation Serif', rtl=False, comments_heading_pos='hide',
|
rating_font='Liberation Serif', rtl=False, comments_heading_pos='hide',
|
||||||
for_qt=False,
|
for_qt=False, vertical_fields=()
|
||||||
):
|
):
|
||||||
if field_list is None:
|
if field_list is None:
|
||||||
field_list = get_field_list(mi)
|
field_list = get_field_list(mi)
|
||||||
@ -108,6 +108,12 @@ def mi_to_html(
|
|||||||
continue
|
continue
|
||||||
if not metadata:
|
if not metadata:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
def value_list(sep, vals):
|
||||||
|
if field in vertical_fields:
|
||||||
|
return '<br/>'.join(vals)
|
||||||
|
return sep.join(vals)
|
||||||
|
|
||||||
if field == 'sort':
|
if field == 'sort':
|
||||||
field = 'title_sort'
|
field = 'title_sort'
|
||||||
if metadata['is_custom'] and metadata['datatype'] in {'bool', 'int', 'float'}:
|
if metadata['is_custom'] and metadata['datatype'] in {'bool', 'int', 'float'}:
|
||||||
@ -162,11 +168,11 @@ def mi_to_html(
|
|||||||
_('Click to see books with {0}: {1}').format(metadata['name'], a(val)), p(val))
|
_('Click to see books with {0}: {1}').format(metadata['name'], a(val)), p(val))
|
||||||
else:
|
else:
|
||||||
all_vals = [v.strip()
|
all_vals = [v.strip()
|
||||||
for v in val.split(metadata['is_multiple']['list_to_ui']) if v.strip()]
|
for v in val.split(metadata['is_multiple']['cache_to_list']) if v.strip()]
|
||||||
links = ['<a href="{}" title="{}">{}</a>'.format(
|
links = ['<a href="{}" title="{}">{}</a>'.format(
|
||||||
search_action(field, x), _('Click to see books with {0}: {1}').format(
|
search_action(field, x), _('Click to see books with {0}: {1}').format(
|
||||||
metadata['name'], a(x)), p(x)) for x in all_vals]
|
metadata['name'], a(x)), p(x)) for x in all_vals]
|
||||||
val = metadata['is_multiple']['list_to_ui'].join(links)
|
val = value_list(metadata['is_multiple']['list_to_ui'], links)
|
||||||
ans.append((field, row % (name, val)))
|
ans.append((field, row % (name, val)))
|
||||||
elif field == 'path':
|
elif field == 'path':
|
||||||
if mi.path:
|
if mi.path:
|
||||||
@ -199,7 +205,7 @@ def mi_to_html(
|
|||||||
} for x in mi.formats)
|
} for x in mi.formats)
|
||||||
fmts = ['<a title="{bpath}{sep}{fname}.{ext}" href="{action}">{fmt}</a>'.format(**x)
|
fmts = ['<a title="{bpath}{sep}{fname}.{ext}" href="{action}">{fmt}</a>'.format(**x)
|
||||||
for x in data]
|
for x in data]
|
||||||
ans.append((field, row % (name, ', '.join(fmts))))
|
ans.append((field, row % (name, value_list(', ', fmts))))
|
||||||
elif field == 'identifiers':
|
elif field == 'identifiers':
|
||||||
urls = urls_from_identifiers(mi.identifiers, sort_results=True)
|
urls = urls_from_identifiers(mi.identifiers, sort_results=True)
|
||||||
links = [
|
links = [
|
||||||
@ -207,7 +213,7 @@ def mi_to_html(
|
|||||||
action('identifier', url=url, name=namel, id_type=id_typ, value=id_val, field='identifiers', book_id=book_id),
|
action('identifier', url=url, name=namel, id_type=id_typ, value=id_val, field='identifiers', book_id=book_id),
|
||||||
a(id_typ), a(id_val), p(namel))
|
a(id_typ), a(id_val), p(namel))
|
||||||
for namel, id_typ, id_val, url in urls]
|
for namel, id_typ, id_val, url in urls]
|
||||||
links = ', '.join(links)
|
links = value_list(', ', links)
|
||||||
if links:
|
if links:
|
||||||
ans.append((field, row % (_('Ids')+':', links)))
|
ans.append((field, row % (_('Ids')+':', links)))
|
||||||
elif field == 'authors':
|
elif field == 'authors':
|
||||||
@ -233,14 +239,14 @@ def mi_to_html(
|
|||||||
authors.append('<a title="%s" href="%s">%s</a>'%(a(lt), action('author', url=link, name=aut, title=lt), aut))
|
authors.append('<a title="%s" href="%s">%s</a>'%(a(lt), action('author', url=link, name=aut, title=lt), aut))
|
||||||
else:
|
else:
|
||||||
authors.append(aut)
|
authors.append(aut)
|
||||||
ans.append((field, row % (name, ' & '.join(authors))))
|
ans.append((field, row % (name, value_list(' & ', authors))))
|
||||||
elif field == 'languages':
|
elif field == 'languages':
|
||||||
if not mi.languages:
|
if not mi.languages:
|
||||||
continue
|
continue
|
||||||
names = filter(None, map(calibre_langcode_to_name, mi.languages))
|
names = filter(None, map(calibre_langcode_to_name, mi.languages))
|
||||||
names = ['<a href="{}" title="{}">{}</a>'.format(search_action_with_data('languages', n, book_id), _(
|
names = ['<a href="{}" title="{}">{}</a>'.format(search_action_with_data('languages', n, book_id), _(
|
||||||
'Search calibre for books with the language: {}').format(n), n) for n in names]
|
'Search calibre for books with the language: {}').format(n), n) for n in names]
|
||||||
ans.append((field, row % (name, ', '.join(names))))
|
ans.append((field, row % (name, value_list(', ', names))))
|
||||||
elif field == 'publisher':
|
elif field == 'publisher':
|
||||||
if not mi.publisher:
|
if not mi.publisher:
|
||||||
continue
|
continue
|
||||||
@ -303,7 +309,7 @@ def mi_to_html(
|
|||||||
search_action_with_data(st, x, book_id, field), _('Click to see books with {0}: {1}').format(
|
search_action_with_data(st, x, book_id, field), _('Click to see books with {0}: {1}').format(
|
||||||
metadata['name'] or field, a(x)), p(x))
|
metadata['name'] or field, a(x)), p(x))
|
||||||
for x in all_vals]
|
for x in all_vals]
|
||||||
val = metadata['is_multiple']['list_to_ui'].join(links)
|
val = value_list(metadata['is_multiple']['list_to_ui'], links)
|
||||||
elif metadata['datatype'] == 'text' or metadata['datatype'] == 'enumeration':
|
elif metadata['datatype'] == 'text' or metadata['datatype'] == 'enumeration':
|
||||||
# text/is_multiple handled above so no need to add the test to the if
|
# text/is_multiple handled above so no need to add the test to the if
|
||||||
try:
|
try:
|
||||||
|
@ -176,7 +176,9 @@ def init_find_in_grouped_search(menu, field, value, book_info):
|
|||||||
|
|
||||||
|
|
||||||
def render_html(mi, vertical, widget, all_fields=False, render_data_func=None, pref_name='book_display_fields'): # {{{
|
def render_html(mi, vertical, widget, all_fields=False, render_data_func=None, pref_name='book_display_fields'): # {{{
|
||||||
func = render_data_func or render_data
|
from calibre.gui2.ui import get_gui
|
||||||
|
func = render_data_func or partial(render_data,
|
||||||
|
vertical_fields=get_gui().current_db.prefs.get('book_details_vertical_categories') or ())
|
||||||
try:
|
try:
|
||||||
table, comment_fields = func(mi, all_fields=all_fields,
|
table, comment_fields = func(mi, all_fields=all_fields,
|
||||||
use_roman_numbers=config['use_roman_numerals_for_series_number'], pref_name=pref_name)
|
use_roman_numbers=config['use_roman_numerals_for_series_number'], pref_name=pref_name)
|
||||||
@ -233,13 +235,15 @@ def get_field_list(fm, use_defaults=False, pref_name='book_display_fields'):
|
|||||||
return [(f, d) for f, d in fieldlist if f in available]
|
return [(f, d) for f, d in fieldlist if f in available]
|
||||||
|
|
||||||
|
|
||||||
def render_data(mi, use_roman_numbers=True, all_fields=False, pref_name='book_display_fields'):
|
def render_data(mi, use_roman_numbers=True, all_fields=False, pref_name='book_display_fields',
|
||||||
|
vertical_fields=()):
|
||||||
field_list = get_field_list(getattr(mi, 'field_metadata', field_metadata), pref_name=pref_name)
|
field_list = get_field_list(getattr(mi, 'field_metadata', field_metadata), pref_name=pref_name)
|
||||||
field_list = [(x, all_fields or display) for x, display in field_list]
|
field_list = [(x, all_fields or display) for x, display in field_list]
|
||||||
return mi_to_html(
|
return mi_to_html(
|
||||||
mi, field_list=field_list, use_roman_numbers=use_roman_numbers, rtl=is_rtl(),
|
mi, field_list=field_list, use_roman_numbers=use_roman_numbers, rtl=is_rtl(),
|
||||||
rating_font=rating_font(), default_author_link=default_author_link(),
|
rating_font=rating_font(), default_author_link=default_author_link(),
|
||||||
comments_heading_pos=gprefs['book_details_comments_heading_pos'], for_qt=True
|
comments_heading_pos=gprefs['book_details_comments_heading_pos'], for_qt=True,
|
||||||
|
vertical_fields=vertical_fields
|
||||||
)
|
)
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
@ -470,6 +470,38 @@ class TBHierarchicalFields(DisplayedFields): # {{{
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
class BDVerticalCats(DisplayedFields): # {{{
|
||||||
|
|
||||||
|
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):
|
||||||
|
fm = self.db.field_metadata
|
||||||
|
cats = [k for k in fm if fm[k]['name'] and fm[k]['is_multiple']]
|
||||||
|
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:
|
||||||
|
vertical_cats = self.db.prefs.get('book_details_vertical_categories') or ()
|
||||||
|
for key in cats:
|
||||||
|
ans.append([key, key in vertical_cats])
|
||||||
|
self.beginResetModel()
|
||||||
|
self.fields = ans
|
||||||
|
self.endResetModel()
|
||||||
|
|
||||||
|
def commit(self):
|
||||||
|
if self.changed:
|
||||||
|
self.db.prefs.set('book_details_vertical_categories', [k for k,v in self.fields if v])
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
class Background(QWidget): # {{{
|
class Background(QWidget): # {{{
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
@ -706,6 +738,10 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.tb_hierarchy_import_layout_button.clicked.connect(partial(self.import_layout,
|
self.tb_hierarchy_import_layout_button.clicked.connect(partial(self.import_layout,
|
||||||
model=self.tb_hierarchical_cats_model))
|
model=self.tb_hierarchical_cats_model))
|
||||||
|
|
||||||
|
self.bd_vertical_cats_model = BDVerticalCats(self.gui.current_db, self.tb_hierarchical_cats)
|
||||||
|
self.bd_vertical_cats_model.dataChanged.connect(self.changed_signal)
|
||||||
|
self.bd_vertical_cats.setModel(self.bd_vertical_cats_model)
|
||||||
|
|
||||||
self.fill_tb_search_order_box()
|
self.fill_tb_search_order_box()
|
||||||
self.tb_search_order_up_button.clicked.connect(self.move_tb_search_up)
|
self.tb_search_order_up_button.clicked.connect(self.move_tb_search_up)
|
||||||
self.tb_search_order_down_button.clicked.connect(self.move_tb_search_down)
|
self.tb_search_order_down_button.clicked.connect(self.move_tb_search_down)
|
||||||
@ -959,6 +995,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.tb_display_model.initialize()
|
self.tb_display_model.initialize()
|
||||||
self.tb_categories_to_part_model.initialize()
|
self.tb_categories_to_part_model.initialize()
|
||||||
self.tb_hierarchical_cats_model.initialize()
|
self.tb_hierarchical_cats_model.initialize()
|
||||||
|
self.bd_vertical_cats_model.initialize()
|
||||||
db = self.gui.current_db
|
db = self.gui.current_db
|
||||||
mi = []
|
mi = []
|
||||||
try:
|
try:
|
||||||
@ -1022,6 +1059,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.display_model.restore_defaults()
|
self.display_model.restore_defaults()
|
||||||
self.em_display_model.restore_defaults()
|
self.em_display_model.restore_defaults()
|
||||||
self.qv_display_model.restore_defaults()
|
self.qv_display_model.restore_defaults()
|
||||||
|
self.bd_vertical_cats_model.restore_defaults()
|
||||||
gprefs.set('tb_search_order', gprefs.defaults['tb_search_order'])
|
gprefs.set('tb_search_order', gprefs.defaults['tb_search_order'])
|
||||||
self.edit_rules.clear()
|
self.edit_rules.clear()
|
||||||
self.icon_rules.clear()
|
self.icon_rules.clear()
|
||||||
@ -1097,6 +1135,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.tb_display_model.commit()
|
self.tb_display_model.commit()
|
||||||
self.tb_categories_to_part_model.commit()
|
self.tb_categories_to_part_model.commit()
|
||||||
self.tb_hierarchical_cats_model.commit()
|
self.tb_hierarchical_cats_model.commit()
|
||||||
|
self.bd_vertical_cats_model.commit()
|
||||||
self.tb_search_order_commit()
|
self.tb_search_order_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)
|
||||||
|
@ -733,14 +733,14 @@ A value of zero means calculate automatically.</string>
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0" colspan="2">
|
<item row="5" column="0" colspan="3">
|
||||||
<widget class="QPushButton" name="id_links_button">
|
<widget class="QPushButton" name="id_links_button">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Create rules to convert &identifiers into links</string>
|
<string>Create rules to convert &identifiers into links</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" colspan="2">
|
<item row="3" column="0" colspan="3">
|
||||||
<widget class="QWidget" name="default_author_link_container" native="true">
|
<widget class="QWidget" name="default_author_link_container" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
@ -750,6 +750,25 @@ A value of zero means calculate automatically.</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="6" column="2">
|
||||||
|
<widget class="QGroupBox" name="groupBox3">
|
||||||
|
<property name="title">
|
||||||
|
<string>Categories on separate lines</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><p>Check the box if you want the category's values displayed on separate lines instead of separated by commas</p></string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="vblayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QListView" name="bd_vertical_cats">
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -811,7 +830,7 @@ A value of zero means calculate automatically.</string>
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="0" column="0" colspan="3">
|
||||||
<layout class="QHBoxLayout">
|
<layout class="QHBoxLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="opt_bd_show_cover">
|
<widget class="QCheckBox" name="opt_bd_show_cover">
|
||||||
@ -855,7 +874,7 @@ A value of zero means calculate automatically.</string>
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0" colspan="2">
|
<item row="1" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_25">
|
<widget class="QLabel" name="label_25">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user