mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
ef109d55a2
@ -434,17 +434,6 @@ locale_for_sorting = ''
|
|||||||
# columns. If False, one column is used.
|
# columns. If False, one column is used.
|
||||||
metadata_single_use_2_cols_for_custom_fields = True
|
metadata_single_use_2_cols_for_custom_fields = True
|
||||||
|
|
||||||
#: Order of custom column(s) in edit metadata
|
|
||||||
# Controls the order that custom columns are listed in edit metadata single
|
|
||||||
# and bulk. The columns listed in the tweak are displayed first and in the
|
|
||||||
# order provided. Any columns not listed are displayed after the listed ones,
|
|
||||||
# in alphabetical order. Do note that this tweak does not change the size of
|
|
||||||
# the edit widgets. Putting comments widgets in this list may result in some
|
|
||||||
# odd widget spacing when using two-column mode.
|
|
||||||
# Enter a comma-separated list of custom field lookup names, as in
|
|
||||||
# metadata_edit_custom_column_order = ['#genre', '#mytags', '#etc']
|
|
||||||
metadata_edit_custom_column_order = []
|
|
||||||
|
|
||||||
#: Edit metadata custom column label width and elision point
|
#: Edit metadata custom column label width and elision point
|
||||||
# Set the width of custom column labels shown in the edit metadata dialogs.
|
# Set the width of custom column labels shown in the edit metadata dialogs.
|
||||||
# If metadata_edit_elide_labels is True then labels wider than the width
|
# If metadata_edit_elide_labels is True then labels wider than the width
|
||||||
|
@ -6,6 +6,7 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from collections import OrderedDict
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from qt.core import (Qt, QComboBox, QLabel, QSpinBox, QDoubleSpinBox,
|
from qt.core import (Qt, QComboBox, QLabel, QSpinBox, QDoubleSpinBox,
|
||||||
@ -749,10 +750,31 @@ widgets = {
|
|||||||
def field_sort_key(y, fm=None):
|
def field_sort_key(y, fm=None):
|
||||||
m1 = fm[y]
|
m1 = fm[y]
|
||||||
name = icu_lower(m1['name'])
|
name = icu_lower(m1['name'])
|
||||||
n1 = 'zzzzz' + name if m1['datatype'] == 'comments' and m1.get('display', {}).get('interpret_as') != 'short-text' else name
|
n1 = 'zzzzz' + name if column_is_comments(y, fm) else name
|
||||||
return sort_key(n1)
|
return sort_key(n1)
|
||||||
|
|
||||||
|
|
||||||
|
def column_is_comments(key, fm):
|
||||||
|
return (fm[key]['datatype'] == 'comments' and
|
||||||
|
fm[key].get('display', {}).get('interpret_as') != 'short-text')
|
||||||
|
|
||||||
|
|
||||||
|
def get_field_list(db, use_defaults=False):
|
||||||
|
fm = db.field_metadata
|
||||||
|
fields = fm.custom_field_keys(include_composites=False)
|
||||||
|
displayable = db.prefs.get('edit_metadata_custom_columns_to_display', None)
|
||||||
|
if use_defaults or displayable is None:
|
||||||
|
fields.sort(key=partial(field_sort_key, fm=fm))
|
||||||
|
return [(k, True) for k in fields]
|
||||||
|
else:
|
||||||
|
field_set = set(fields)
|
||||||
|
result = OrderedDict({k:v for k,v in displayable if k in field_set})
|
||||||
|
for k in fields:
|
||||||
|
if k not in result:
|
||||||
|
result[k] = True
|
||||||
|
return [(k,v) for k,v in result.items()]
|
||||||
|
|
||||||
|
|
||||||
def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, parent=None):
|
def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, parent=None):
|
||||||
def widget_factory(typ, key):
|
def widget_factory(typ, key):
|
||||||
if bulk:
|
if bulk:
|
||||||
@ -765,36 +787,22 @@ def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, pa
|
|||||||
fm = db.field_metadata
|
fm = db.field_metadata
|
||||||
|
|
||||||
# Get list of all non-composite custom fields. We must make widgets for these
|
# Get list of all non-composite custom fields. We must make widgets for these
|
||||||
fields = fm.custom_field_keys(include_composites=False)
|
cols = [k[0] for k in get_field_list(db) if k[1]]
|
||||||
cols_to_display = fields
|
# This deals with the historical behavior where comments fields go to the
|
||||||
cols_to_display.sort(key=partial(field_sort_key, fm=fm))
|
# bottom, starting on the left hand side. If a comment field is moved to
|
||||||
|
# somewhere else then it isn't moved to either side.
|
||||||
# This will contain the fields in the order to display them
|
comments_at_end = 0
|
||||||
cols = []
|
for k in cols[::-1]:
|
||||||
|
if not column_is_comments(k, fm):
|
||||||
# The fields named here must be first in the widget list
|
break
|
||||||
tweak_cols = tweaks['metadata_edit_custom_column_order']
|
comments_at_end += 1
|
||||||
comments_in_tweak = 0
|
comments_not_at_end = len([k for k in cols if column_is_comments(k, fm)]) - comments_at_end
|
||||||
for key in (tweak_cols or ()):
|
|
||||||
# Add the key if it really exists in the database
|
|
||||||
if key in cols_to_display:
|
|
||||||
cols.append(key)
|
|
||||||
if fm[key]['datatype'] == 'comments' and fm[key].get('display', {}).get('interpret_as') != 'short-text':
|
|
||||||
comments_in_tweak += 1
|
|
||||||
|
|
||||||
# Add all the remaining fields
|
|
||||||
comments_not_in_tweak = 0
|
|
||||||
for key in cols_to_display:
|
|
||||||
if key not in cols:
|
|
||||||
cols.append(key)
|
|
||||||
if fm[key]['datatype'] == 'comments' and fm[key].get('display', {}).get('interpret_as') != 'short-text':
|
|
||||||
comments_not_in_tweak += 1
|
|
||||||
|
|
||||||
count = len(cols)
|
count = len(cols)
|
||||||
layout_rows_for_comments = 9
|
layout_rows_for_comments = 9
|
||||||
if two_column:
|
if two_column:
|
||||||
turnover_point = int(((count - comments_not_in_tweak + 1) +
|
turnover_point = int(((count - comments_at_end + 1) +
|
||||||
int(comments_in_tweak*(layout_rows_for_comments-1)))/2)
|
int(comments_not_at_end*(layout_rows_for_comments-1)))/2)
|
||||||
else:
|
else:
|
||||||
# Avoid problems with multi-line widgets
|
# Avoid problems with multi-line widgets
|
||||||
turnover_point = count + 1000
|
turnover_point = count + 1000
|
||||||
@ -813,22 +821,22 @@ def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, pa
|
|||||||
dt = fm[key]['datatype']
|
dt = fm[key]['datatype']
|
||||||
if dt == 'composite' or (bulk and dt == 'comments'):
|
if dt == 'composite' or (bulk and dt == 'comments'):
|
||||||
continue
|
continue
|
||||||
is_comments = dt == 'comments' and fm[key].get('display', {}).get('interpret_as') != 'short-text'
|
is_comments = column_is_comments(key, fm)
|
||||||
w = widget_factory(dt, fm[key]['colnum'])
|
w = widget_factory(dt, fm[key]['colnum'])
|
||||||
ans.append(w)
|
ans.append(w)
|
||||||
if two_column and is_comments:
|
if two_column and is_comments:
|
||||||
# Here for compatibility with old layout. Comments always started
|
# Here for compatibility with old layout. Comments always started
|
||||||
# in the left column
|
# in the left column
|
||||||
comments_in_tweak -= 1
|
comments_not_at_end -= 1
|
||||||
# no special processing if the comment field was named in the tweak
|
# no special processing if the comment field was named in the tweak
|
||||||
if comments_in_tweak < 0 and comments_not_in_tweak > 0:
|
if comments_not_at_end < 0 and comments_at_end > 0:
|
||||||
# Force a turnover, adding comments widgets below max_row.
|
# Force a turnover, adding comments widgets below max_row.
|
||||||
# Save the row to return to if we turn over again
|
# Save the row to return to if we turn over again
|
||||||
column = 0
|
column = 0
|
||||||
row = max_row
|
row = max_row
|
||||||
base_row = row
|
base_row = row
|
||||||
turnover_point = row + int((comments_not_in_tweak * layout_rows_for_comments)/2)
|
turnover_point = row + int((comments_at_end * layout_rows_for_comments)/2)
|
||||||
comments_not_in_tweak = 0
|
comments_at_end = 0
|
||||||
|
|
||||||
l = QGridLayout()
|
l = QGridLayout()
|
||||||
if is_comments:
|
if is_comments:
|
||||||
|
@ -76,10 +76,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
|
|
||||||
r('bools_are_tristate', db.prefs, restart_required=True)
|
r('bools_are_tristate', db.prefs, restart_required=True)
|
||||||
r('numeric_collation', prefs, restart_required=True)
|
r('numeric_collation', prefs, restart_required=True)
|
||||||
r = self.register
|
|
||||||
choices = [(_('Default'), 'default'), (_('Compact Metadata'), 'alt1'),
|
|
||||||
(_('All on 1 tab'), 'alt2')]
|
|
||||||
r('edit_metadata_single_layout', gprefs, choices=choices)
|
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
ConfigWidgetBase.initialize(self)
|
ConfigWidgetBase.initialize(self)
|
||||||
|
@ -75,13 +75,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="14" column="1">
|
|
||||||
<widget class="QComboBox" name="opt_edit_metadata_single_layout">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Choose a different layout for the Edit metadata dialog. The compact metadata layout favors editing custom metadata over changing covers and formats.</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="15" column="0" colspan="2">
|
<item row="15" column="0" colspan="2">
|
||||||
<widget class="QGroupBox" name="groupBox_5">
|
<widget class="QGroupBox" name="groupBox_5">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -175,16 +168,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="14" column="0">
|
|
||||||
<widget class="QLabel" name="edit_metadata_single_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Edit metadata (single) &layout:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>opt_edit_metadata_single_layout</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -22,6 +22,7 @@ from calibre.ebooks.metadata.book.render import DEFAULT_AUTHOR_LINK
|
|||||||
from calibre.constants import ismacos, iswindows
|
from calibre.constants import ismacos, iswindows
|
||||||
from calibre.ebooks.metadata.sources.prefs import msprefs
|
from calibre.ebooks.metadata.sources.prefs import msprefs
|
||||||
from calibre.gui2 import default_author_link
|
from calibre.gui2 import default_author_link
|
||||||
|
from calibre.gui2.custom_column_widgets import get_field_list as em_get_field_list
|
||||||
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, CommaSeparatedList
|
||||||
from calibre.gui2.preferences.look_feel_ui import Ui_Form
|
from calibre.gui2.preferences.look_feel_ui import Ui_Form
|
||||||
@ -259,8 +260,8 @@ class DisplayedFields(QAbstractListModel): # {{{
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if not name:
|
if not name:
|
||||||
name = field
|
return field
|
||||||
return name
|
return f'{name} ({field})'
|
||||||
if role == Qt.ItemDataRole.CheckStateRole:
|
if role == Qt.ItemDataRole.CheckStateRole:
|
||||||
return Qt.CheckState.Checked if visible else Qt.CheckState.Unchecked
|
return Qt.CheckState.Checked if visible else Qt.CheckState.Unchecked
|
||||||
if role == Qt.ItemDataRole.DecorationRole and field.startswith('#'):
|
if role == Qt.ItemDataRole.DecorationRole and field.startswith('#'):
|
||||||
@ -328,6 +329,23 @@ def move_field_down(widget, model):
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
class EMDisplayedFields(DisplayedFields): # {{{
|
||||||
|
def __init__(self, db, parent=None):
|
||||||
|
DisplayedFields.__init__(self, db, parent)
|
||||||
|
|
||||||
|
def initialize(self, use_defaults=False):
|
||||||
|
self.beginResetModel()
|
||||||
|
self.fields = [[x[0], x[1]] for x in
|
||||||
|
em_get_field_list(self.db, use_defaults=use_defaults)]
|
||||||
|
self.endResetModel()
|
||||||
|
self.changed = True
|
||||||
|
|
||||||
|
def commit(self):
|
||||||
|
if self.changed:
|
||||||
|
self.db.new_api.set_pref('edit_metadata_custom_columns_to_display', self.fields)
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
class QVDisplayedFields(DisplayedFields): # {{{
|
class QVDisplayedFields(DisplayedFields): # {{{
|
||||||
|
|
||||||
def __init__(self, db, parent=None):
|
def __init__(self, db, parent=None):
|
||||||
@ -515,6 +533,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
key=lambda x:sort_key(x[0]))
|
key=lambda x:sort_key(x[0]))
|
||||||
r('field_under_covers_in_grid', db.prefs, choices=choices)
|
r('field_under_covers_in_grid', db.prefs, choices=choices)
|
||||||
|
|
||||||
|
choices = [(_('Default'), 'default'), (_('Compact Metadata'), 'alt1'),
|
||||||
|
(_('All on 1 tab'), 'alt2')]
|
||||||
|
r('edit_metadata_single_layout', gprefs,
|
||||||
|
choices=[(_('Default'), 'default'), (_('Compact Metadata'), 'alt1'),
|
||||||
|
(_('All on 1 tab'), 'alt2')])
|
||||||
|
|
||||||
self.current_font = self.initial_font = None
|
self.current_font = self.initial_font = None
|
||||||
self.change_font_button.clicked.connect(self.change_font)
|
self.change_font_button.clicked.connect(self.change_font)
|
||||||
|
|
||||||
@ -527,6 +551,15 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
connect_lambda(self.df_down_button.clicked, self,
|
connect_lambda(self.df_down_button.clicked, self,
|
||||||
lambda self: move_field_down(self.field_display_order, self.display_model))
|
lambda self: move_field_down(self.field_display_order, self.display_model))
|
||||||
|
|
||||||
|
self.em_display_model = EMDisplayedFields(self.gui.current_db,
|
||||||
|
self.em_display_order)
|
||||||
|
self.em_display_model.dataChanged.connect(self.changed_signal)
|
||||||
|
self.em_display_order.setModel(self.em_display_model)
|
||||||
|
connect_lambda(self.em_up_button.clicked, self,
|
||||||
|
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.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)
|
||||||
self.qv_display_model.dataChanged.connect(self.changed_signal)
|
self.qv_display_model.dataChanged.connect(self.changed_signal)
|
||||||
@ -648,6 +681,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.current_font = self.initial_font = font
|
self.current_font = self.initial_font = font
|
||||||
self.update_font_display()
|
self.update_font_display()
|
||||||
self.display_model.initialize()
|
self.display_model.initialize()
|
||||||
|
self.em_display_model.initialize()
|
||||||
self.qv_display_model.initialize()
|
self.qv_display_model.initialize()
|
||||||
db = self.gui.current_db
|
db = self.gui.current_db
|
||||||
mi = []
|
mi = []
|
||||||
@ -709,6 +743,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.changed_signal.emit()
|
self.changed_signal.emit()
|
||||||
self.update_font_display()
|
self.update_font_display()
|
||||||
self.display_model.restore_defaults()
|
self.display_model.restore_defaults()
|
||||||
|
self.em_display_model.restore_defaults()
|
||||||
self.qv_display_model.restore_defaults()
|
self.qv_display_model.restore_defaults()
|
||||||
self.edit_rules.clear()
|
self.edit_rules.clear()
|
||||||
self.icon_rules.clear()
|
self.icon_rules.clear()
|
||||||
@ -779,6 +814,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
QApplication.setFont(self.font_display.font())
|
QApplication.setFont(self.font_display.font())
|
||||||
rr = True
|
rr = True
|
||||||
self.display_model.commit()
|
self.display_model.commit()
|
||||||
|
self.em_display_model.commit()
|
||||||
self.qv_display_model.commit()
|
self.qv_display_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)
|
||||||
|
@ -881,6 +881,102 @@ A value of zero means calculate automatically.</string>
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="edit_metadata_tab">
|
||||||
|
<attribute name="icon">
|
||||||
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
<normaloff>:/images/book.png</normaloff>:/images/book.png</iconset>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Edit metadata</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_61">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout1">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="edit_metadata_single_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Edit metadata (single) &layout:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>opt_edit_metadata_single_layout</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="opt_edit_metadata_single_layout">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Choose a different layout for the Edit metadata dialog. The compact metadata layout favors editing custom metadata over changing covers and formats.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Select the custom columns to display in the dialogs and their order</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QToolButton" name="em_down_button">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Move down</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
<normaloff>:/images/arrow-down.png</normaloff>:/images/arrow-down.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QToolButton" name="em_up_button">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Move up</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
<normaloff>:/images/arrow-up.png</normaloff>:/images/arrow-up.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<spacer name="verticalSpacer_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" rowspan="3">
|
||||||
|
<widget class="QListView" name="em_display_order">
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
<widget class="QWidget" name="tag_browser_tab">
|
<widget class="QWidget" name="tag_browser_tab">
|
||||||
<attribute name="icon">
|
<attribute name="icon">
|
||||||
<iconset resource="../../../../resources/images.qrc">
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user