This commit is contained in:
Kovid Goyal 2023-04-24 10:29:12 +05:30
commit c04b7dd482
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 67 additions and 34 deletions

View File

@ -574,3 +574,17 @@ allow_template_database_functions_in_composites = False
# for https://whatever URLs. %u is replaced by the URL to be opened. The scheme
# takes a glob pattern allowing a single entry to match multiple URL types.
openers_by_scheme = {}
#: Change standard column heading text to some value
# Use the dictionary below to change a column heading. The format of the
# dictionary is
# {lookup_name: new_heading, ...}
# The new_heading must be unique: no two columns can have the same heading.
# This tweak works only with standard columns: it cannot be used to change
# the heading for a custom column. If a custom column has the same heading as
# one provided here then a number will appended to the custom column's heading
# to make it unique.
#
# Example:
# alternate_column_headings = {'authors':'Writers', 'size':'MBytes'}
alternate_column_headings = {}

View File

@ -38,7 +38,7 @@ from calibre.utils.date import (
UNDEFINED_DATE, as_local_time, dt_factory, is_date_undefined, qt_to_dt,
)
from calibre.utils.icu import sort_key
from calibre.utils.localization import calibre_langcode_to_name, ngettext
from calibre.utils.localization import calibre_langcode_to_name
from calibre.utils.resources import get_path as P
from calibre.utils.search_query_parser import ParseException, SearchQueryParser
from polyglot.builtins import iteritems, itervalues, string_or_bytes
@ -192,20 +192,12 @@ class BooksModel(QAbstractTableModel): # {{{
self.bi_font = QFont(self.bold_font)
self.bi_font.setItalic(True)
self.styled_columns = {}
self.orig_headers = {
'title' : _("Title"),
'ondevice' : _("On Device"),
'authors' : _("Author(s)"),
'size' : _("Size (MB)"),
'timestamp' : _("Date"),
'pubdate' : _('Published'),
'rating' : _('Rating'),
'publisher' : _("Publisher"),
'tags' : _("Tags"),
'series' : ngettext("Series", 'Series', 1),
'last_modified' : _('Modified'),
'languages' : _('Languages'),
}
possible_columns = ('title', 'ondevice', 'authors', 'size', 'timestamp',
'pubdate', 'rating', 'publisher', 'tags', 'series',
'last_modified', 'languages', 'formats', 'id', 'path')
from calibre.library.field_metadata import FieldMetadata
fm = FieldMetadata()
self.orig_headers = {k: fm[k]['name'] for k in possible_columns}
self.db = None
@ -829,6 +821,10 @@ class BooksModel(QAbstractTableModel): # {{{
def renderer(field, decorator=False):
idfunc = self.db.id
if field == 'id':
def func(idx):
return idfunc(idx)
return func
fffunc = self.db.new_api.fast_field_for
field_obj = self.db.new_api.fields[field]
m = field_obj.metadata.copy()
@ -953,7 +949,7 @@ class BooksModel(QAbstractTableModel): # {{{
return func
self.dc = {f:renderer(f) for f in 'title authors size timestamp pubdate last_modified rating publisher tags series ondevice languages'.split()}
self.dc = {f:renderer(f) for f in self.orig_headers.keys()}
self.dc_decorator = {f:renderer(f, True) for f in ('ondevice',)}
for col in self.custom_columns:

View File

@ -808,8 +808,8 @@ class BooksView(QTableView): # {{{
state = {}
state['hidden_columns'] = [cm[i] for i in range(h.count())
if h.isSectionHidden(i) and cm[i] != 'ondevice']
state['last_modified_injected'] = True
state['languages_injected'] = True
for f in ('last_modified', 'languages', 'formats', 'id', 'path'):
state[f+'_injected'] = True
state['sort_history'] = \
self.cleanup_sort_history(self.model().sort_history, ignore_column_map=self.is_library_view)
state['column_positions'] = {}
@ -923,7 +923,7 @@ class BooksView(QTableView): # {{{
def get_default_state(self):
old_state = {
'hidden_columns': ['last_modified', 'languages'],
'hidden_columns': ['last_modified', 'languages', 'formats', 'id', 'path'],
'sort_history':[DEFAULT_SORT],
'column_positions': {},
'column_sizes': {},
@ -931,9 +931,9 @@ class BooksView(QTableView): # {{{
'size':'center',
'timestamp':'center',
'pubdate':'center'},
'last_modified_injected': True,
'languages_injected': True,
}
for f in ('last_modified', 'languages', 'formats', 'id', 'path'):
old_state[f+'_injected'] = True
h = self.column_header
cm = self.column_map
for i in range(h.count()):
@ -965,18 +965,14 @@ class BooksView(QTableView): # {{{
db.new_api.set_pref(name, ans)
else:
injected = False
if not ans.get('last_modified_injected', False):
injected = True
ans['last_modified_injected'] = True
hc = ans.get('hidden_columns', [])
if 'last_modified' not in hc:
hc.append('last_modified')
if not ans.get('languages_injected', False):
injected = True
ans['languages_injected'] = True
hc = ans.get('hidden_columns', [])
if 'languages' not in hc:
hc.append('languages')
for f in ('last_modified', 'languages', 'formats', 'id', 'path'):
if not ans.get(f+'_injected', False):
print('injecting', f)
injected = True
ans[f+'_injected'] = True
hc = ans.get('hidden_columns', [])
if f not in hc:
hc.append(f)
if injected:
db.new_api.set_pref(name, ans)
return ans

View File

@ -5,6 +5,7 @@ Created on 25 May 2010
'''
import traceback
import sys
from collections import OrderedDict
from calibre.utils.config_base import tweaks
@ -197,7 +198,7 @@ def _builtin_field_metadata():
'datatype':'int',
'is_multiple':{},
'kind':'field',
'name':None,
'name': _('Id'),
'search_terms':['id'],
'is_custom':False,
'is_category':False,
@ -411,6 +412,15 @@ class FieldMetadata:
self._tb_cats[k]['display'] = {}
self._tb_cats[k]['is_editable'] = True
self._add_search_terms_to_map(k, v['search_terms'])
alternate_headings = tweaks.get('alternate_column_headings', {})
if alternate_headings:
existing_headings = {k['name'] for k in self._tb_cats.values() if k['name']}
for k,v in alternate_headings.items():
if k in self._tb_cats.keys():
v = self.get_unique_field_heading(v)
existing_headings.discard(self._tb_cats[k]['name'])
existing_headings.add(v)
self._tb_cats[k]['name'] = v
self._tb_cats['timestamp']['display'] = {
'date_format': tweaks['gui_timestamp_display_format']}
self._tb_cats['pubdate']['display'] = {
@ -454,6 +464,10 @@ class FieldMetadata:
def __ne__(self, other):
return not self.__eq__(other)
def set_field_heading(self, key, heading):
if key in self._tb_cats.keys():
self._tb_cats[key]['name'] = heading
def sortable_field_keys(self):
return [k for k in self._tb_cats.keys()
if self._tb_cats[k]['kind']=='field' and
@ -560,6 +574,18 @@ class FieldMetadata:
l[k] = self._tb_cats[k]
return l
def get_unique_field_heading(self, name):
# Verify column heading is unique. Can only happen if the tweak is set
if tweaks.get('alternate_column_headings', {}):
existing_names = {icu_lower(c['name']) for c in self._tb_cats.values() if c['name'] is not None}
t = icu_lower(name)
if t in existing_names:
for i in range(1, sys.maxsize):
if (t + '_' + str(i)) not in existing_names:
name = name + '_' + str(i)
break
return name
def add_custom_field(self, label, table, column, datatype, colnum, name,
display, is_editable, is_multiple, is_category,
is_csp=False):
@ -568,6 +594,7 @@ class FieldMetadata:
raise ValueError('Duplicate custom field [%s]'%(label))
if datatype not in self.VALID_DATA_TYPES:
raise ValueError('Unknown datatype %s for field %s'%(datatype, key))
name = self.get_unique_field_heading(name)
self._tb_cats[key] = {'table':table, 'column':column,
'datatype':datatype, 'is_multiple':is_multiple,
'kind':'field', 'name':name,