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.
|
||||
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
|
||||
# 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
|
||||
|
@ -6,6 +6,7 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
from functools import partial
|
||||
|
||||
from qt.core import (Qt, QComboBox, QLabel, QSpinBox, QDoubleSpinBox,
|
||||
@ -749,10 +750,31 @@ widgets = {
|
||||
def field_sort_key(y, fm=None):
|
||||
m1 = fm[y]
|
||||
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)
|
||||
|
||||
|
||||
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 widget_factory(typ, key):
|
||||
if bulk:
|
||||
@ -765,36 +787,22 @@ def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, pa
|
||||
fm = db.field_metadata
|
||||
|
||||
# Get list of all non-composite custom fields. We must make widgets for these
|
||||
fields = fm.custom_field_keys(include_composites=False)
|
||||
cols_to_display = fields
|
||||
cols_to_display.sort(key=partial(field_sort_key, fm=fm))
|
||||
|
||||
# This will contain the fields in the order to display them
|
||||
cols = []
|
||||
|
||||
# The fields named here must be first in the widget list
|
||||
tweak_cols = tweaks['metadata_edit_custom_column_order']
|
||||
comments_in_tweak = 0
|
||||
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
|
||||
cols = [k[0] for k in get_field_list(db) if k[1]]
|
||||
# This deals with the historical behavior where comments fields go to the
|
||||
# bottom, starting on the left hand side. If a comment field is moved to
|
||||
# somewhere else then it isn't moved to either side.
|
||||
comments_at_end = 0
|
||||
for k in cols[::-1]:
|
||||
if not column_is_comments(k, fm):
|
||||
break
|
||||
comments_at_end += 1
|
||||
comments_not_at_end = len([k for k in cols if column_is_comments(k, fm)]) - comments_at_end
|
||||
|
||||
count = len(cols)
|
||||
layout_rows_for_comments = 9
|
||||
if two_column:
|
||||
turnover_point = int(((count - comments_not_in_tweak + 1) +
|
||||
int(comments_in_tweak*(layout_rows_for_comments-1)))/2)
|
||||
turnover_point = int(((count - comments_at_end + 1) +
|
||||
int(comments_not_at_end*(layout_rows_for_comments-1)))/2)
|
||||
else:
|
||||
# Avoid problems with multi-line widgets
|
||||
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']
|
||||
if dt == 'composite' or (bulk and dt == 'comments'):
|
||||
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'])
|
||||
ans.append(w)
|
||||
if two_column and is_comments:
|
||||
# Here for compatibility with old layout. Comments always started
|
||||
# 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
|
||||
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.
|
||||
# Save the row to return to if we turn over again
|
||||
column = 0
|
||||
row = max_row
|
||||
base_row = row
|
||||
turnover_point = row + int((comments_not_in_tweak * layout_rows_for_comments)/2)
|
||||
comments_not_in_tweak = 0
|
||||
turnover_point = row + int((comments_at_end * layout_rows_for_comments)/2)
|
||||
comments_at_end = 0
|
||||
|
||||
l = QGridLayout()
|
||||
if is_comments:
|
||||
|
@ -76,10 +76,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
|
||||
r('bools_are_tristate', db.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):
|
||||
ConfigWidgetBase.initialize(self)
|
||||
|
@ -75,13 +75,6 @@
|
||||
</item>
|
||||
</widget>
|
||||
</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">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="sizePolicy">
|
||||
@ -175,16 +168,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -22,6 +22,7 @@ from calibre.ebooks.metadata.book.render import DEFAULT_AUTHOR_LINK
|
||||
from calibre.constants import ismacos, iswindows
|
||||
from calibre.ebooks.metadata.sources.prefs import msprefs
|
||||
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.preferences import ConfigWidgetBase, test_widget, CommaSeparatedList
|
||||
from calibre.gui2.preferences.look_feel_ui import Ui_Form
|
||||
@ -259,8 +260,8 @@ class DisplayedFields(QAbstractListModel): # {{{
|
||||
except:
|
||||
pass
|
||||
if not name:
|
||||
name = field
|
||||
return name
|
||||
return field
|
||||
return f'{name} ({field})'
|
||||
if role == Qt.ItemDataRole.CheckStateRole:
|
||||
return Qt.CheckState.Checked if visible else Qt.CheckState.Unchecked
|
||||
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): # {{{
|
||||
|
||||
def __init__(self, db, parent=None):
|
||||
@ -515,6 +533,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
key=lambda x:sort_key(x[0]))
|
||||
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.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,
|
||||
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_order)
|
||||
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.update_font_display()
|
||||
self.display_model.initialize()
|
||||
self.em_display_model.initialize()
|
||||
self.qv_display_model.initialize()
|
||||
db = self.gui.current_db
|
||||
mi = []
|
||||
@ -709,6 +743,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
self.changed_signal.emit()
|
||||
self.update_font_display()
|
||||
self.display_model.restore_defaults()
|
||||
self.em_display_model.restore_defaults()
|
||||
self.qv_display_model.restore_defaults()
|
||||
self.edit_rules.clear()
|
||||
self.icon_rules.clear()
|
||||
@ -779,6 +814,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
QApplication.setFont(self.font_display.font())
|
||||
rr = True
|
||||
self.display_model.commit()
|
||||
self.em_display_model.commit()
|
||||
self.qv_display_model.commit()
|
||||
self.edit_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>
|
||||
</layout>
|
||||
</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">
|
||||
<attribute name="icon">
|
||||
<iconset resource="../../../../resources/images.qrc">
|
||||
|
Loading…
x
Reference in New Issue
Block a user