For default values, use native types in the display. Add a lot of error checking.

This commit is contained in:
Charles Haley 2020-07-05 08:34:59 +01:00
parent 248edbe8fb
commit 082d2ae8b3
2 changed files with 86 additions and 30 deletions

View File

@ -101,16 +101,8 @@ def _add_default_custom_column_values(mi, fm):
if not mi.get_user_metadata(cc, make_copy=False):
mi.set_user_metadata(cc, col)
dt = col['datatype']
if dt == 'bool':
dv = {_('yes'): 'true', 'yes': 'true',
_('no'): 'false', 'no': 'false'}.get(icu_lower(dv), '')
elif dt == 'datetime' and (icu_lower(dv) in [_('now'), 'now']):
if dt == 'datetime' and icu_lower(dv) == 'now':
dv = nowf()
elif dt == 'rating':
try:
dv = int(dv) * 2
except:
dv = None
mi.set(cc, dv)
except:
traceback.print_exc()

View File

@ -17,6 +17,7 @@ from PyQt5.Qt import (
)
from calibre.gui2 import error_dialog
from calibre.utils.date import parse_date, UNDEFINED_DATE
from polyglot.builtins import iteritems, unicode_type, range, map
@ -127,8 +128,7 @@ class CreateCustomColumn(QDialog):
self.shortcuts.setVisible(False)
idx = current_row
if idx < 0:
self.simple_error(_('No column selected'),
_('No column has been selected'))
self.simple_error(_('No column selected'), _('No column has been selected'))
return
col = current_key
if col not in parent.custcols:
@ -178,8 +178,22 @@ class CreateCustomColumn(QDialog):
elif ct == 'rating':
self.allow_half_stars.setChecked(bool(c['display'].get('allow_half_stars', False)))
if ct not in ['composite', '*composite']:
self.default_value.setText(c['display'].get('default_value', ''))
# Default values
dv = c['display'].get('default_value', None)
if dv is not None:
if ct == 'bool':
self.default_value.setText(_('Yes') if dv else _('No'))
elif ct == 'datetime':
self.default_value.setText(_('Now') if dv == 'now' else dv)
elif ct == 'rating':
if self.allow_half_stars.isChecked():
self.default_value.setText(str(dv/2))
else:
self.default_value.setText(str(dv//2))
elif ct in ['int', 'float']:
self.default_value.setText(unicode_type(dv))
elif ct not in ['composite', '*composite']:
self.default_value.setText(dv)
self.datatype_changed()
if ct in ['text', 'composite', 'enumeration']:
@ -396,12 +410,11 @@ class CreateCustomColumn(QDialog):
# Default value
self.default_value = dv = QLineEdit(self)
dv.setToolTip('<p>' + (_('Default value when a new book is added to the '
'library. For Date columns enter the word "Now" or "%s", or the '
'date as yyyy-mm-dd. For Yes/No columns enter "Yes" or "%s", or '
'"No" or "%s". For Text with a fixed set of values enter one of '
'the permitted values. For Rating columns enter a number between '
'0 and 5.') % ('now', 'yes', 'no')) + '</p>')
dv.setToolTip('<p>' + _('Default value when a new book is added to the '
'library. For Date columns enter the word "Now", or the date as '
'yyyy-mm-dd. For Yes/No columns enter "Yes" "No". For Text with '
'a fixed set of values enter one of the permitted values. For '
'Rating columns enter a number between 0 and 5.') + '</p>')
self.default_value_label = add_row(_('Default value'), dv)
self.resize(self.sizeHint())
@ -528,15 +541,30 @@ class CreateCustomColumn(QDialog):
display_dict = {}
default_val = (unicode_type(self.default_value.text()).strip()
if col_type != 'composite' else None)
if col_type == 'datetime':
if unicode_type(self.format_box.text()).strip():
display_dict = {'date_format':unicode_type(self.format_box.text()).strip()}
else:
display_dict = {'date_format': None}
if default_val:
if default_val == _('Now'):
display_dict['default_value'] = 'now'
else:
try:
tv = parse_date(default_val)
except:
tv = UNDEFINED_DATE
if tv == UNDEFINED_DATE:
return self.simple_error(_('Invalid default value'),
_('The default value must be "Now" or a date'))
display_dict['default_value'] = default_val
elif col_type == 'composite':
if not unicode_type(self.composite_box.text()).strip():
return self.simple_error('', _('You must enter a template for'
' composite columns'))
return self.simple_error('', _('You must enter a template for '
'composite columns'))
display_dict = {'composite_template':unicode_type(self.composite_box.text()).strip(),
'composite_sort': ['text', 'number', 'date', 'bool']
[self.composite_sort_by.currentIndex()],
@ -545,8 +573,8 @@ class CreateCustomColumn(QDialog):
}
elif col_type == 'enumeration':
if not unicode_type(self.enum_box.text()).strip():
return self.simple_error('', _('You must enter at least one'
' value for enumeration columns'))
return self.simple_error('', _('You must enter at least one '
'value for enumeration columns'))
l = [v.strip() for v in unicode_type(self.enum_box.text()).split(',') if v.strip()]
l_lower = [v.lower() for v in l]
for i,v in enumerate(l_lower):
@ -560,13 +588,16 @@ class CreateCustomColumn(QDialog):
c = []
if len(c) != 0 and len(c) != len(l):
return self.simple_error('', _('The colors box must be empty or '
'contain the same number of items as the value box'))
'contain the same number of items as the value box'))
for tc in c:
if tc not in QColor.colorNames() and not re.match("#(?:[0-9a-f]{3}){1,4}",tc,re.I):
return self.simple_error('',
_('The color {0} is unknown').format(tc))
return self.simple_error('', _('The color {0} is unknown').format(tc))
display_dict = {'enum_values': l, 'enum_colors': c}
if default_val:
if default_val not in l:
return self.simple_error(_('Invalid default value'),
_('The default value must be one of the permitted values'))
display_dict['default_value'] = default_val
elif col_type == 'text' and is_multiple:
display_dict = {'is_names': self.is_names.isChecked()}
elif col_type in ['int', 'float']:
@ -574,17 +605,50 @@ class CreateCustomColumn(QDialog):
display_dict = {'number_format':unicode_type(self.format_box.text()).strip()}
else:
display_dict = {'number_format': None}
if default_val:
try:
if col_type == 'int':
msg = _('The default value must be an integer')
tv = int(default_val)
display_dict['default_value'] = tv
else:
msg = _('The default value must be a real number')
tv = float(default_val)
display_dict['default_value'] = tv
except:
return self.simple_error(_('Invalid default value'), msg)
elif col_type == 'comments':
display_dict['heading_position'] = unicode_type(self.comments_heading_position.currentData())
display_dict['interpret_as'] = unicode_type(self.comments_type.currentData())
elif col_type == 'rating':
display_dict['allow_half_stars'] = bool(self.allow_half_stars.isChecked())
half_stars = bool(self.allow_half_stars.isChecked())
display_dict['allow_half_stars'] = half_stars
if default_val:
try:
tv = int((float(default_val) if half_stars else int(default_val)) * 2)
except:
tv = -1
if tv < 0 or tv > 10:
if half_stars:
return self.simple_error(_('Invalid default value'),
_('The default value must be a real number between 0 and 5.0'))
else:
return self.simple_error(_('Invalid default value'),
_('The default value must be an integer between 0 and 5'))
display_dict['default_value'] = tv
elif col_type == 'bool':
if default_val:
tv = {_('Yes'): True, _('No'): False}.get(default_val, None)
if tv is None:
return self.simple_error(_('Invalid default value'),
_('The default value must be "Yes" or "No"'))
display_dict['default_value'] = tv
if col_type in ['text', 'composite', 'enumeration'] and not is_multiple:
display_dict['use_decorations'] = self.use_decorations.checkState()
if col_type != 'composite':
display_dict['default_value'] = unicode_type(self.default_value.text())
if default_val and 'default_value' not in display_dict:
display_dict['default_value'] = default_val
display_dict['description'] = self.description_box.text().strip()