Port calibredb custom_columns

This commit is contained in:
Kovid Goyal 2017-05-02 09:10:27 +05:30
parent f0155f4b2a
commit 7ebd16989d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 161 additions and 18 deletions

View File

@ -4,19 +4,89 @@
from __future__ import absolute_import, division, print_function, unicode_literals
import json
from calibre import prints
from calibre.db.legacy import LibraryDatabase
from calibre.library.custom_columns import CustomColumns
readonly = False
version = 0 # change this if you change signature of implementation()
no_remote = True
def implementation(db, notify_changes, *args):
is_remote = notify_changes is not None
is_remote
raise NotImplementedError()
def option_parser(get_parser, args):
pass
parser = get_parser(
_(
'''\
%prog add_custom_column [options] label name datatype
Create a custom column. label is the machine friendly name of the column. Should
not contain spaces or colons. name is the human friendly name of the column.
datatype is one of: {0}
'''
).format(', '.join(sorted(CustomColumns.CUSTOM_DATA_TYPES)))
)
parser.add_option(
'--is-multiple',
default=False,
action='store_true',
help=_(
'This column stores tag like data (i.e. '
'multiple comma separated values). Only '
'applies if datatype is text.'
)
)
parser.add_option(
'--display',
default='{}',
help=_(
'A dictionary of options to customize how '
'the data in this column will be interpreted. This is a JSON '
' string. For enumeration columns, use '
'--display="{\\"enum_values\\":[\\"val1\\", \\"val2\\"]}"'
'\n'
'There are many options that can go into the display variable.'
'The options by column type are:\n'
'composite: composite_template, composite_sort, make_category,'
'contains_html, use_decorations\n'
'datetime: date_format\n'
'enumeration: enum_values, enum_colors, use_decorations\n'
'int, float: number_format\n'
'text: is_names, use_decorations\n'
'\n'
'The best way to find legal combinations is to create a custom '
'column of the appropriate type in the GUI then look at the '
'backup OPF for a book (ensure that a new OPF has been created '
'since the column was added). You will see the JSON for the '
'"display" for the new column in the OPF.'
)
)
return parser
def do_add_custom_column(db, label, name, datatype, is_multiple, display):
num = db.create_custom_column(
label, name, datatype, is_multiple, display=display
)
prints('Custom column created with id: %s' % num)
def main(opts, args, dbctx):
raise NotImplementedError('TODO: implement this')
if len(args) < 3:
raise SystemExit(_('You must specify label, name and datatype'))
do_add_custom_column(
dbctx.db, args[0], args[1], args[2], opts.is_multiple,
json.loads(opts.display)
)
# Update the stored field_metadata
dbctx.db.close()
db = LibraryDatabase(dbctx.db.library_path)
m = db.field_metadata.all_metadata()
db.new_api.set_pref('field_metadata', m)
return 0

View File

@ -4,19 +4,45 @@
from __future__ import absolute_import, division, print_function, unicode_literals
readonly = False
from pprint import pformat
from calibre import prints
readonly = True
version = 0 # change this if you change signature of implementation()
def implementation(db, notify_changes, *args):
is_remote = notify_changes is not None
is_remote
return db.backend.custom_column_label_map
def option_parser(get_parser, args):
pass
parser = get_parser(
_(
'''\
%prog custom_columns [options]
List available custom columns. Shows column labels and ids.
'''
)
)
parser.add_option(
'-d',
'--details',
default=False,
action='store_true',
help=_('Show details for each column.')
)
return parser
def main(opts, args, dbctx):
raise NotImplementedError('TODO: implement this')
for col, data in dbctx.run('custom_columns').iteritems():
if opts.details:
prints(col)
print()
prints(pformat(data))
print('\n')
else:
prints(col, '(%d)'%data['num'])
return 0

View File

@ -4,19 +4,67 @@
from __future__ import absolute_import, division, print_function, unicode_literals
from calibre import prints
from calibre.db.legacy import LibraryDatabase
readonly = False
version = 0 # change this if you change signature of implementation()
no_remote = True
def implementation(db, notify_changes, *args):
is_remote = notify_changes is not None
is_remote
raise NotImplementedError()
def option_parser(get_parser, args):
pass
parser = get_parser(
_(
'''\
%prog remove_custom_column [options] label
Remove the custom column identified by label. You can see available
columns with the custom_columns command.
'''
)
)
parser.add_option(
'-f',
'--force',
default=False,
action='store_true',
help=_('Do not ask for confirmation')
)
return parser
def do_remove_custom_column(db, label, force):
if not force:
q = raw_input(
_('You will lose all data in the column: %s.'
' Are you sure (y/n)? ') % label
)
if q.lower().strip() != _('y'):
return
try:
db.delete_custom_column(label=label)
except KeyError:
raise SystemExit(
_(
'No column named %s found. You must use column labels, not titles.'
' Use calibredb custom_columns to get a list of labels.'
) % label
)
prints('Column %r removed.' % label)
def main(opts, args, dbctx):
raise NotImplementedError('TODO: implement this')
if len(args) < 1:
raise SystemExit(_('Error: You must specify a column label'))
do_remove_custom_column(dbctx.db, args[0], opts.force)
# Update the stored field_metadata
dbctx.db.close()
db = LibraryDatabase(dbctx.db.library_path)
m = db.field_metadata.all_metadata()
db.new_api.set_pref('field_metadata', m)
return 0

View File

@ -20,10 +20,9 @@ from calibre.utils.serialize import MSGPACK_MIME
COMMANDS = (
'list', 'add', 'remove', 'add_format', 'remove_format', 'show_metadata',
'set_metadata', 'export', 'catalog',
'saved_searches',
# 'add_custom_column',
# 'custom_columns', 'remove_custom_column', 'set_custom', 'restore_database',
'set_metadata', 'export', 'catalog', 'saved_searches', 'add_custom_column',
'custom_columns', 'remove_custom_column',
# 'set_custom', 'restore_database',
# 'check_library', 'list_categories', 'backup_metadata', 'clone', 'embed_metadata',
# 'search'
)

View File

@ -695,7 +695,7 @@ class LibraryDatabase(object):
self.new_api.delete_custom_column(label, num)
def create_custom_column(self, label, name, datatype, is_multiple, editable=True, display={}):
self.new_api.create_custom_column(label, name, datatype, is_multiple, editable=editable, display=display)
return self.new_api.create_custom_column(label, name, datatype, is_multiple, editable=editable, display=display)
def set_custom_column_metadata(self, num, name=None, label=None, is_editable=None, display=None,
notify=True, update_last_modified=False):