Fixes #1903348 [[Enhancement] Add a clear button to clear permitted values when editing a custom columns](https://bugs.launchpad.net/calibre/+bug/1903348)
This commit is contained in:
Kovid Goyal 2020-11-08 17:11:22 +05:30
commit aa9e76aa78
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -70,6 +70,21 @@ class Base(object):
except:
pass
def finish_ui_setup(self, parent, edit_widget):
self.was_none = False
w = QWidget(parent)
self.widgets.append(w)
l = QHBoxLayout()
l.setContentsMargins(0, 0, 0, 0)
w.setLayout(l)
self.editor = editor = edit_widget(parent)
l.addWidget(editor)
self.clear_button = QToolButton(parent)
self.clear_button.setIcon(QIcon(I('trash.png')))
self.clear_button.clicked.connect(self.set_to_undefined)
self.clear_button.setToolTip(_('Clear {0}').format(self.col_metadata['name']))
l.addWidget(self.clear_button)
def initialize(self, book_id):
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
val = self.normalize_db_val(val)
@ -114,18 +129,20 @@ class Base(object):
class SimpleText(Base):
def setup_ui(self, parent):
self.editor = QLineEdit(parent)
self.widgets = [QLabel(label_string(self.col_metadata['name']), parent),
QLineEdit(parent)]
self.editor]
self.editor.setClearButtonEnabled(True)
def setter(self, val):
self.widgets[1].setText(unicode_type(val or ''))
self.editor.setText(unicode_type(val or ''))
def getter(self):
return self.widgets[1].text().strip()
return self.editor.text().strip()
def connect_data_changed(self, slot):
self.widgets[1].textChanged.connect(slot)
self.signals_to_disconnect.append(self.widgets[1].textChanged)
self.editor.textChanged.connect(slot)
self.signals_to_disconnect.append(self.editor.textChanged)
class LongText(Base):
@ -179,7 +196,7 @@ class Bool(Base):
if self.db.new_api.pref('bools_are_tristate'):
c = QToolButton(parent)
c.setText(_('Clear'))
c.setIcon(QIcon(I('trash.png')))
c.setToolTip(_('Clear {}').format(name))
l.addWidget(c)
c.clicked.connect(self.set_to_cleared)
@ -225,23 +242,10 @@ class Int(Base):
self.editor.setRange(-1000000, 100000000)
def finish_ui_setup(self, parent, edit_widget):
self.was_none = False
w = QWidget(parent)
self.widgets.append(w)
l = QHBoxLayout()
l.setContentsMargins(0, 0, 0, 0)
w.setLayout(l)
self.editor = editor = edit_widget(parent)
editor.setRange(-1000000, 100000000)
editor.setSpecialValueText(_('Undefined'))
editor.setSingleStep(1)
editor.valueChanged.connect(self.valueChanged)
l.addWidget(editor)
self.clear_button = QToolButton(parent)
self.clear_button.setIcon(QIcon(I('trash.png')))
self.clear_button.clicked.connect(self.set_to_undefined)
self.clear_button.setToolTip(_('Clear {0}').format(self.col_metadata['name']))
l.addWidget(self.clear_button)
Base.finish_ui_setup(self, parent, edit_widget)
self.editor.setSpecialValueText(_('Undefined'))
self.editor.setSingleStep(1)
self.editor.valueChanged.connect(self.valueChanged)
def setter(self, val):
if val is None:
@ -276,24 +280,26 @@ class Float(Int):
self.editor.setRange(-1000000., float(100000000))
self.editor.setDecimals(2)
class Rating(Base):
def setup_ui(self, parent):
allow_half_stars = self.col_metadata['display'].get('allow_half_stars', False)
self.widgets = [QLabel(label_string(self.col_metadata['name']), parent),
RatingEditor(parent=parent, is_half_star=allow_half_stars)]
self.widgets = [QLabel(label_string(self.col_metadata['name']), parent)]
self.finish_ui_setup(parent, partial(RatingEditor, is_half_star=allow_half_stars))
def set_to_undefined(self):
self.editor.setCurrentIndex(0)
def setter(self, val):
val = max(0, min(int(val or 0), 10))
self.widgets[1].rating_value = val
self.editor.rating_value = val
def getter(self):
return self.widgets[1].rating_value or None
return self.editor.rating_value or None
def connect_data_changed(self, slot):
self.widgets[1].currentTextChanged.connect(slot)
self.signals_to_disconnect.append(self.widgets[1].currentTextChanged)
self.editor.currentTextChanged.connect(slot)
self.signals_to_disconnect.append(self.editor.currentTextChanged)
class DateTimeEdit(DateTimeEditBase):
@ -493,19 +499,22 @@ class Text(Base):
w.set_add_separator(tweaks['authors_completer_append_separator'])
w.get_editor_button().clicked.connect(self.edit)
w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
self.set_to_undefined = w.clear
else:
w = EditWithComplete(parent)
w.set_separator(None)
w.setSizeAdjustPolicy(w.AdjustToMinimumContentsLengthWithIcon)
w.setMinimumContentsLength(25)
self.widgets = [QLabel(label_string(self.col_metadata['name']), parent), w]
self.set_to_undefined = w.clearEditText
self.widgets = [QLabel(label_string(self.col_metadata['name']), parent)]
self.finish_ui_setup(parent, lambda parent: w)
def initialize(self, book_id):
values = list(self.db.all_custom(num=self.col_id))
values.sort(key=sort_key)
self.book_id = book_id
self.widgets[1].clear()
self.widgets[1].update_items_cache(values)
self.editor.clear()
self.editor.update_items_cache(values)
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
if isinstance(val, list):
if not self.col_metadata.get('display', {}).get('is_names', False):
@ -515,23 +524,23 @@ class Text(Base):
if self.col_metadata['is_multiple']:
self.setter(val)
else:
self.widgets[1].setText(val)
self.editor.setText(val)
self.initial_val = self.current_val
def setter(self, val):
if self.col_metadata['is_multiple']:
if not val:
val = []
self.widgets[1].setText(self.sep['list_to_ui'].join(val))
self.editor.setText(self.sep['list_to_ui'].join(val))
def getter(self):
if self.col_metadata['is_multiple']:
val = unicode_type(self.widgets[1].text()).strip()
val = unicode_type(self.editor.text()).strip()
ans = [x.strip() for x in val.split(self.sep['ui_to_list']) if x.strip()]
if not ans:
ans = None
return ans
val = unicode_type(self.widgets[1].currentText()).strip()
val = unicode_type(self.editor.currentText()).strip()
if not val:
val = None
return val
@ -556,9 +565,9 @@ class Text(Base):
def connect_data_changed(self, slot):
if self.col_metadata['is_multiple']:
s = self.widgets[1].tags_box.currentTextChanged
s = self.editor.tags_box.currentTextChanged
else:
s = self.widgets[1].currentTextChanged
s = self.editor.currentTextChanged
s.connect(slot)
self.signals_to_disconnect.append(s)
@ -571,7 +580,8 @@ class Series(Base):
w.setSizeAdjustPolicy(w.AdjustToMinimumContentsLengthWithIcon)
w.setMinimumContentsLength(25)
self.name_widget = w
self.widgets = [QLabel(label_string(self.col_metadata['name']), parent), w]
self.widgets = [QLabel(label_string(self.col_metadata['name']), parent)]
self.finish_ui_setup(parent, lambda parent: w)
w.editTextChanged.connect(self.series_changed)
w = QLabel(label_string(self.col_metadata['name'])+_(' index'), parent)
@ -585,6 +595,10 @@ class Series(Base):
w.setToolTip(get_tooltip(self.col_metadata, add_index=True))
self.widgets.append(w)
def set_to_undefined(self):
self.name_widget.clearEditText()
self.idx_widget.setValue(1.0)
def initialize(self, book_id):
values = list(self.db.all_custom(num=self.col_id))
values.sort(key=sort_key)
@ -639,7 +653,7 @@ class Series(Base):
mi.set('#' + self.col_metadata['label'], val, extra=s_index)
def connect_data_changed(self, slot):
for s in self.widgets[1].editTextChanged, self.widgets[3].valueChanged:
for s in self.name_widget.editTextChanged, self.idx_widget.valueChanged:
s.connect(slot)
self.signals_to_disconnect.append(s)
@ -648,18 +662,17 @@ class Enumeration(Base):
def setup_ui(self, parent):
self.parent = parent
self.widgets = [QLabel(label_string(self.col_metadata['name']), parent),
QComboBox(parent)]
w = self.widgets[1]
self.widgets = [QLabel(label_string(self.col_metadata['name']), parent)]
self.finish_ui_setup(parent, QComboBox)
vals = self.col_metadata['display']['enum_values']
w.addItem('')
self.editor.addItem('')
for v in vals:
w.addItem(v)
self.editor.addItem(v)
def initialize(self, book_id):
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
val = self.normalize_db_val(val)
idx = self.widgets[1].findText(val)
idx = self.editor.findText(val)
if idx < 0:
error_dialog(self.parent, '',
_('The enumeration "{0}" contains an invalid value '
@ -668,14 +681,14 @@ class Enumeration(Base):
show=True, show_copy_button=False)
idx = 0
self.widgets[1].setCurrentIndex(idx)
self.editor.setCurrentIndex(idx)
self.initial_val = self.current_val
def setter(self, val):
self.widgets[1].setCurrentIndex(self.widgets[1].findText(val))
self.editor.setCurrentIndex(self.editor.findText(val))
def getter(self):
return unicode_type(self.widgets[1].currentText())
return unicode_type(self.editor.currentText())
def normalize_db_val(self, val):
if val is None:
@ -687,9 +700,12 @@ class Enumeration(Base):
val = None
return val
def set_to_undefined(self):
self.editor.setCurrentIndex(0)
def connect_data_changed(self, slot):
self.widgets[1].currentIndexChanged.connect(slot)
self.signals_to_disconnect.append(self.widgets[1].currentIndexChanged)
self.editor.currentIndexChanged.connect(slot)
self.signals_to_disconnect.append(self.editor.currentIndexChanged)
def comments_factory(db, key, parent):
@ -879,6 +895,16 @@ class BulkBase(Base):
ans = list(ans)
return ans
def finish_ui_setup(self, parent):
self.was_none = False
l = self.widgets[1].layout()
self.clear_button = QToolButton(parent)
self.clear_button.setIcon(QIcon(I('trash.png')))
self.clear_button.setToolTip(_('Clear {0}').format(self.col_metadata['name']))
l.insertWidget(1, self.clear_button)
l.insertStretch(2)
self.clear_button.clicked.connect(self.set_to_undefined)
def initialize(self, book_ids):
self.initial_val = val = self.get_initial_value(book_ids)
val = self.normalize_db_val(val)
@ -948,7 +974,8 @@ class BulkBool(BulkBase, Bool):
def setup_ui(self, parent):
self.make_widgets(parent, QComboBox)
items = [_('Yes'), _('No')]
if not self.db.new_api.pref('bools_are_tristate'):
self.bools_are_tristate = self.db.new_api.pref('bools_are_tristate')
if not self.bools_are_tristate:
items.append('')
else:
items.append(_('Undefined'))
@ -957,10 +984,17 @@ class BulkBool(BulkBase, Bool):
for icon, text in zip(icons, items):
self.main_widget.addItem(QIcon(icon), text)
self.main_widget.blockSignals(False)
if self.bools_are_tristate:
# Add clear if bools are tristate
self.finish_ui_setup(parent)
def set_to_undefined(self):
# Only called if bools are tristate
self.main_widget.setCurrentIndex(2)
def getter(self):
val = self.main_widget.currentIndex()
if not self.db.new_api.pref('bools_are_tristate'):
if not self.bools_are_tristate:
return {2: False, 1: False, 0: True}[val]
else:
return {2: None, 1: False, 0: True}[val]
@ -975,14 +1009,13 @@ class BulkBool(BulkBase, Bool):
return
val = self.gui_val
val = self.normalize_ui_val(val)
if not self.db.new_api.pref('bools_are_tristate') and val is None:
if not self.bools_are_tristate and val is None:
val = False
self.db.set_custom_bulk(book_ids, val, num=self.col_id, notify=notify)
def a_c_checkbox_changed(self):
if not self.ignore_change_signals:
if not self.db.new_api.pref('bools_are_tristate') and \
self.main_widget.currentIndex() == 2:
if not self.bools_are_tristate and self.main_widget.currentIndex() == 2:
self.a_c_checkbox.setChecked(False)
else:
self.a_c_checkbox.setChecked(True)
@ -996,17 +1029,10 @@ class BulkInt(BulkBase):
self.finish_ui_setup(parent)
def finish_ui_setup(self, parent):
self.was_none = False
BulkBase.finish_ui_setup(self, parent)
self.main_widget.setSpecialValueText(_('Undefined'))
self.main_widget.setSingleStep(1)
self.main_widget.valueChanged.connect(self.valueChanged)
l = self.widgets[1].layout()
self.clear_button = QToolButton(parent)
self.clear_button.setIcon(QIcon(I('trash.png')))
self.clear_button.setToolTip(_('Clear {0}').format(self.col_metadata['name']))
l.insertWidget(1, self.clear_button)
l.insertStretch(2)
self.clear_button.clicked.connect(self.set_to_undefined)
def setter(self, val):
if val is None:
@ -1029,7 +1055,6 @@ class BulkInt(BulkBase):
def set_to_undefined(self):
self.main_widget.setValue(-1000000)
class BulkFloat(BulkInt):
def setup_ui(self, parent):
@ -1047,6 +1072,10 @@ class BulkRating(BulkBase):
def setup_ui(self, parent):
allow_half_stars = self.col_metadata['display'].get('allow_half_stars', False)
self.make_widgets(parent, partial(RatingEditor, is_half_star=allow_half_stars))
self.finish_ui_setup(parent)
def set_to_undefined(self):
self.main_widget.setCurrentIndex(0)
def setter(self, val):
val = max(0, min(int(val or 0), 10))
@ -1274,12 +1303,16 @@ class BulkEnumeration(BulkBase, Enumeration):
def setup_ui(self, parent):
self.parent = parent
self.make_widgets(parent, QComboBox)
self.finish_ui_setup(parent)
vals = self.col_metadata['display']['enum_values']
self.main_widget.blockSignals(True)
self.main_widget.addItem('')
self.main_widget.addItems(vals)
self.main_widget.blockSignals(False)
def set_to_undefined(self):
self.main_widget.setCurrentIndex(0)
def getter(self):
return unicode_type(self.main_widget.currentText())
@ -1359,6 +1392,10 @@ class BulkText(BulkBase):
self.main_widget.setMinimumContentsLength(25)
self.ignore_change_signals = False
self.parent = parent
self.finish_ui_setup(parent)
def set_to_undefined(self):
self.main_widget.clearEditText()
def initialize(self, book_ids):
self.main_widget.update_items_cache(self.all_values)