Refactor bulk custom widgets to add an 'apply changes' checkbox to each widget

This commit is contained in:
Charles Haley 2011-01-27 13:15:35 +00:00
parent ceea626264
commit ff2c0f0d2c

View File

@ -151,12 +151,27 @@ class DateEdit(QDateEdit):
def set_to_today(self): def set_to_today(self):
self.setDate(now()) self.setDate(now())
def set_to_clear(self):
self.setDate(UNDEFINED_QDATE)
class DateTime(Base): class DateTime(Base):
def setup_ui(self, parent): def setup_ui(self, parent):
cm = self.col_metadata cm = self.col_metadata
self.widgets = [QLabel('&'+cm['name']+':', parent), DateEdit(parent), self.widgets = [QLabel('&'+cm['name']+':', parent), DateEdit(parent)]
QLabel(''), QPushButton(_('Set \'%s\' to today')%cm['name'], parent)] self.widgets.append(QLabel(''))
w = QWidget(parent)
self.widgets.append(w)
l = QHBoxLayout()
l.setContentsMargins(0, 0, 0, 0)
w.setLayout(l)
l.addStretch(1)
self.today_button = QPushButton(_('Set \'%s\' to today')%cm['name'], parent)
l.addWidget(self.today_button)
self.clear_button = QPushButton(_('Clear \'%s\'')%cm['name'], parent)
l.addWidget(self.clear_button)
l.addStretch(2)
w = self.widgets[1] w = self.widgets[1]
format = cm['display'].get('date_format','') format = cm['display'].get('date_format','')
if not format: if not format:
@ -165,7 +180,8 @@ class DateTime(Base):
w.setCalendarPopup(True) w.setCalendarPopup(True)
w.setMinimumDate(UNDEFINED_QDATE) w.setMinimumDate(UNDEFINED_QDATE)
w.setSpecialValueText(_('Undefined')) w.setSpecialValueText(_('Undefined'))
self.widgets[3].clicked.connect(w.set_to_today) self.today_button.clicked.connect(w.set_to_today)
self.clear_button.clicked.connect(w.set_to_clear)
def setter(self, val): def setter(self, val):
if val is None: if val is None:
@ -470,11 +486,48 @@ class BulkBase(Base):
self.setter(val) self.setter(val)
def commit(self, book_ids, notify=False): def commit(self, book_ids, notify=False):
if not self.a_c_checkbox.isChecked():
return
val = self.gui_val val = self.gui_val
val = self.normalize_ui_val(val) val = self.normalize_ui_val(val)
if val != self.initial_val: if val != self.initial_val:
self.db.set_custom_bulk(book_ids, val, num=self.col_id, notify=notify) self.db.set_custom_bulk(book_ids, val, num=self.col_id, notify=notify)
def make_widgets(self, parent, main_widget_class, extra_label_text=''):
w = QWidget(parent)
self.widgets = [QLabel('&'+self.col_metadata['name']+':', w), w]
l = QHBoxLayout()
l.setContentsMargins(0, 0, 0, 0)
w.setLayout(l)
self.main_widget = main_widget_class(w)
l.addWidget(self.main_widget)
l.setStretchFactor(self.main_widget, 10)
self.a_c_checkbox = QCheckBox( _('Apply changes'), w)
l.addWidget(self.a_c_checkbox)
self.ignore_change_signals = True
# connect to the various changed signals so we can auto-update the
# apply changes checkbox
if hasattr(self.main_widget, 'editTextChanged'):
# editable combobox widgets
self.main_widget.editTextChanged.connect(self.a_c_checkbox_changed)
if hasattr(self.main_widget, 'textChanged'):
# lineEdit widgets
self.main_widget.textChanged.connect(self.a_c_checkbox_changed)
if hasattr(self.main_widget, 'currentIndexChanged'):
# combobox widgets
self.main_widget.currentIndexChanged[int].connect(self.a_c_checkbox_changed)
if hasattr(self.main_widget, 'valueChanged'):
# spinbox widgets
self.main_widget.valueChanged.connect(self.a_c_checkbox_changed)
if hasattr(self.main_widget, 'dateChanged'):
# dateEdit widgets
self.main_widget.dateChanged.connect(self.a_c_checkbox_changed)
def a_c_checkbox_changed(self):
if not self.ignore_change_signals:
self.a_c_checkbox.setChecked(True)
class BulkBool(BulkBase, Bool): class BulkBool(BulkBase, Bool):
def get_initial_value(self, book_ids): def get_initial_value(self, book_ids):
@ -484,58 +537,144 @@ class BulkBool(BulkBase, Bool):
if tweaks['bool_custom_columns_are_tristate'] == 'no' and val is None: if tweaks['bool_custom_columns_are_tristate'] == 'no' and val is None:
val = False val = False
if value is not None and value != val: if value is not None and value != val:
return 'nochange' return None
value = val value = val
return value return value
def setup_ui(self, parent): def setup_ui(self, parent):
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent), self.make_widgets(parent, QComboBox)
QComboBox(parent)] items = [_('Yes'), _('No'), _('Undefined')]
w = self.widgets[1] icons = [I('ok.png'), I('list_remove.png'), I('blank.png')]
items = [_('Yes'), _('No'), _('Undefined'), _('Do not change')] self.main_widget.blockSignals(True)
icons = [I('ok.png'), I('list_remove.png'), I('blank.png'), I('blank.png')]
for icon, text in zip(icons, items): for icon, text in zip(icons, items):
w.addItem(QIcon(icon), text) self.main_widget.addItem(QIcon(icon), text)
self.main_widget.blockSignals(False)
def getter(self): def getter(self):
val = self.widgets[1].currentIndex() val = self.main_widget.currentIndex()
return {3: 'nochange', 2: None, 1: False, 0: True}[val] return {2: None, 1: False, 0: True}[val]
def setter(self, val): def setter(self, val):
val = {'nochange': 3, None: 2, False: 1, True: 0}[val] val = {None: 2, False: 1, True: 0}[val]
self.widgets[1].setCurrentIndex(val) self.main_widget.setCurrentIndex(val)
self.ignore_change_signals = False
def commit(self, book_ids, notify=False): def commit(self, book_ids, notify=False):
if not self.a_c_checkbox.isChecked():
return
val = self.gui_val val = self.gui_val
val = self.normalize_ui_val(val) val = self.normalize_ui_val(val)
if val != self.initial_val and val != 'nochange': if tweaks['bool_custom_columns_are_tristate'] == 'no' and val is None:
if tweaks['bool_custom_columns_are_tristate'] == 'no' and val is None: val = False
val = False self.db.set_custom_bulk(book_ids, val, num=self.col_id, notify=notify)
self.db.set_custom_bulk(book_ids, val, num=self.col_id, notify=notify)
class BulkInt(BulkBase, Int): class BulkInt(BulkBase):
pass
class BulkFloat(BulkBase, Float): def setup_ui(self, parent):
pass self.make_widgets(parent, QSpinBox)
self.main_widget.setRange(-100, sys.maxint)
self.main_widget.setSpecialValueText(_('Undefined'))
self.main_widget.setSingleStep(1)
class BulkRating(BulkBase, Rating): def setter(self, val):
pass if val is None:
val = self.main_widget.minimum()
else:
val = int(val)
self.main_widget.setValue(val)
self.ignore_change_signals = False
class BulkDateTime(BulkBase, DateTime): def getter(self):
pass val = self.main_widget.value()
if val == self.main_widget.minimum():
val = None
return val
class BulkFloat(BulkInt):
def setup_ui(self, parent):
self.make_widgets(parent, QDoubleSpinBox)
self.main_widget.setRange(-100., float(sys.maxint))
self.main_widget.setDecimals(2)
self.main_widget.setSpecialValueText(_('Undefined'))
self.main_widget.setSingleStep(1)
class BulkRating(BulkBase):
def setup_ui(self, parent):
self.make_widgets(parent, QSpinBox)
self.main_widget.setRange(0, 5)
self.main_widget.setSuffix(' '+_('star(s)'))
self.main_widget.setSpecialValueText(_('Unrated'))
self.main_widget.setSingleStep(1)
def setter(self, val):
if val is None:
val = 0
self.main_widget.setValue(int(round(val/2.)))
self.ignore_change_signals = False
def getter(self):
val = self.main_widget.value()
if val == 0:
val = None
else:
val *= 2
return val
class BulkDateTime(BulkBase):
def setup_ui(self, parent):
cm = self.col_metadata
self.make_widgets(parent, DateEdit)
self.widgets.append(QLabel(''))
w = QWidget(parent)
self.widgets.append(w)
l = QHBoxLayout()
l.setContentsMargins(0, 0, 0, 0)
w.setLayout(l)
l.addStretch(1)
self.today_button = QPushButton(_('Set \'%s\' to today')%cm['name'], parent)
l.addWidget(self.today_button)
self.clear_button = QPushButton(_('Clear \'%s\'')%cm['name'], parent)
l.addWidget(self.clear_button)
l.addStretch(2)
w = self.main_widget
format = cm['display'].get('date_format','')
if not format:
format = 'dd MMM yyyy'
w.setDisplayFormat(format)
w.setCalendarPopup(True)
w.setMinimumDate(UNDEFINED_QDATE)
w.setSpecialValueText(_('Undefined'))
self.today_button.clicked.connect(w.set_to_today)
self.clear_button.clicked.connect(w.set_to_clear)
def setter(self, val):
if val is None:
val = self.main_widget.minimumDate()
else:
val = QDate(val.year, val.month, val.day)
self.main_widget.setDate(val)
self.ignore_change_signals = False
def getter(self):
val = self.main_widget.date()
if val == UNDEFINED_QDATE:
val = None
else:
val = qt_to_dt(val)
return val
class BulkSeries(BulkBase): class BulkSeries(BulkBase):
def setup_ui(self, parent): def setup_ui(self, parent):
self.make_widgets(parent, EnComboBox)
values = self.all_values = list(self.db.all_custom(num=self.col_id)) values = self.all_values = list(self.db.all_custom(num=self.col_id))
values.sort(key=sort_key) values.sort(key=sort_key)
w = EnComboBox(parent) self.main_widget.setSizeAdjustPolicy(self.main_widget.AdjustToMinimumContentsLengthWithIcon)
w.setSizeAdjustPolicy(w.AdjustToMinimumContentsLengthWithIcon) self.main_widget.setMinimumContentsLength(25)
w.setMinimumContentsLength(25)
self.name_widget = w
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent), w]
self.widgets.append(QLabel('', parent)) self.widgets.append(QLabel('', parent))
w = QWidget(parent) w = QWidget(parent)
layout = QHBoxLayout(w) layout = QHBoxLayout(w)
@ -555,15 +694,24 @@ class BulkSeries(BulkBase):
layout.addWidget(self.series_start_number) layout.addWidget(self.series_start_number)
layout.addItem(QSpacerItem(20, 10, QSizePolicy.Expanding, QSizePolicy.Minimum)) layout.addItem(QSpacerItem(20, 10, QSizePolicy.Expanding, QSizePolicy.Minimum))
self.widgets.append(w) self.widgets.append(w)
self.idx_widget.stateChanged.connect(self.check_changed_checkbox)
self.force_number.stateChanged.connect(self.check_changed_checkbox)
self.series_start_number.valueChanged.connect(self.check_changed_checkbox)
self.remove_series.stateChanged.connect(self.check_changed_checkbox)
self.ignore_change_signals = False
def check_changed_checkbox(self):
self.a_c_checkbox.setChecked(True)
def initialize(self, book_id): def initialize(self, book_id):
self.idx_widget.setChecked(False) self.idx_widget.setChecked(False)
for c in self.all_values: for c in self.all_values:
self.name_widget.addItem(c) self.main_widget.addItem(c)
self.name_widget.setEditText('') self.main_widget.setEditText('')
self.a_c_checkbox.setChecked(False)
def getter(self): def getter(self):
n = unicode(self.name_widget.currentText()).strip() n = unicode(self.main_widget.currentText()).strip()
i = self.idx_widget.checkState() i = self.idx_widget.checkState()
f = self.force_number.checkState() f = self.force_number.checkState()
s = self.series_start_number.value() s = self.series_start_number.value()
@ -571,6 +719,8 @@ class BulkSeries(BulkBase):
return n, i, f, s, r return n, i, f, s, r
def commit(self, book_ids, notify=False): def commit(self, book_ids, notify=False):
if not self.a_c_checkbox.isChecked():
return
val, update_indices, force_start, at_value, clear = self.gui_val val, update_indices, force_start, at_value, clear = self.gui_val
val = None if clear else self.normalize_ui_val(val) val = None if clear else self.normalize_ui_val(val)
if clear or val != '': if clear or val != '':
@ -598,9 +748,9 @@ class BulkEnumeration(BulkBase, Enumeration):
def get_initial_value(self, book_ids): def get_initial_value(self, book_ids):
value = None value = None
ret_value = None first = True
dialog_shown = False dialog_shown = False
for i,book_id in enumerate(book_ids): for book_id in book_ids:
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True) val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
if val and val not in self.col_metadata['display']['enum_values']: if val and val not in self.col_metadata['display']['enum_values']:
if not dialog_shown: if not dialog_shown:
@ -610,44 +760,32 @@ class BulkEnumeration(BulkBase, Enumeration):
self.col_metadata['name']), self.col_metadata['name']),
show=True, show_copy_button=False) show=True, show_copy_button=False)
dialog_shown = True dialog_shown = True
ret_value = ' nochange ' if first:
elif (value is not None and value != val) or (val and i != 0): value = val
ret_value = ' nochange ' first = False
value = val elif value != val:
if ret_value is None: value = None
return value if not value:
return ret_value self.ignore_change_signals = False
return value
def setup_ui(self, parent): def setup_ui(self, parent):
self.parent = parent self.make_widgets(parent, QComboBox)
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
QComboBox(parent)]
w = self.widgets[1]
vals = self.col_metadata['display']['enum_values'] vals = self.col_metadata['display']['enum_values']
w.addItem('Do Not Change') self.main_widget.blockSignals(True)
w.addItem('') self.main_widget.addItem('')
for v in vals: self.main_widget.addItems(vals)
w.addItem(v) self.main_widget.blockSignals(False)
def getter(self): def getter(self):
if self.widgets[1].currentIndex() == 0: return unicode(self.main_widget.currentText())
return ' nochange '
return unicode(self.widgets[1].currentText())
def setter(self, val): def setter(self, val):
if val == ' nochange ': if val is None:
self.widgets[1].setCurrentIndex(0) self.main_widget.setCurrentIndex(0)
else: else:
if val is None: self.main_widget.setCurrentIndex(self.main_widget.findText(val))
self.widgets[1].setCurrentIndex(1) self.ignore_change_signals = False
else:
self.widgets[1].setCurrentIndex(self.widgets[1].findText(val))
def commit(self, book_ids, notify=False):
val = self.gui_val
val = self.normalize_ui_val(val)
if val != self.initial_val and val != ' nochange ':
self.db.set_custom_bulk(book_ids, val, num=self.col_id, notify=notify)
class RemoveTags(QWidget): class RemoveTags(QWidget):
@ -658,11 +796,10 @@ class RemoveTags(QWidget):
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
self.tags_box = CompleteLineEdit(parent, values) self.tags_box = CompleteLineEdit(parent, values)
layout.addWidget(self.tags_box, stretch = 1) layout.addWidget(self.tags_box, stretch=3)
# self.tags_box.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
self.checkbox = QCheckBox(_('Remove all tags'), parent) self.checkbox = QCheckBox(_('Remove all tags'), parent)
layout.addWidget(self.checkbox) layout.addWidget(self.checkbox)
layout.addStretch(1)
self.setLayout(layout) self.setLayout(layout)
self.connect(self.checkbox, SIGNAL('stateChanged(int)'), self.box_touched) self.connect(self.checkbox, SIGNAL('stateChanged(int)'), self.box_touched)
@ -679,39 +816,45 @@ class BulkText(BulkBase):
values = self.all_values = list(self.db.all_custom(num=self.col_id)) values = self.all_values = list(self.db.all_custom(num=self.col_id))
values.sort(key=sort_key) values.sort(key=sort_key)
if self.col_metadata['is_multiple']: if self.col_metadata['is_multiple']:
w = CompleteLineEdit(parent, values) self.make_widgets(parent, CompleteLineEdit,
w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) extra_label_text=_('tags to add'))
self.widgets = [QLabel('&'+self.col_metadata['name']+': ' + self.main_widget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
_('tags to add'), parent), w] self.adding_widget = self.main_widget
self.adding_widget = w
w = RemoveTags(parent, values) w = RemoveTags(parent, values)
self.widgets.append(QLabel('&'+self.col_metadata['name']+': ' + self.widgets.append(QLabel('&'+self.col_metadata['name']+': ' +
_('tags to remove'), parent)) _('tags to remove'), parent))
self.widgets.append(w) self.widgets.append(w)
self.removing_widget = w self.removing_widget = w
w.tags_box.textChanged.connect(self.a_c_checkbox_changed)
w.checkbox.stateChanged.connect(self.a_c_checkbox_changed)
else: else:
w = EnComboBox(parent) self.make_widgets(parent, EnComboBox)
w.setSizeAdjustPolicy(w.AdjustToMinimumContentsLengthWithIcon) self.main_widget.setSizeAdjustPolicy(
w.setMinimumContentsLength(25) self.main_widget.AdjustToMinimumContentsLengthWithIcon)
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent), w] self.main_widget.setMinimumContentsLength(25)
self.ignore_change_signals = False
def initialize(self, book_ids): def initialize(self, book_ids):
if self.col_metadata['is_multiple']: if self.col_metadata['is_multiple']:
self.widgets[1].update_items_cache(self.all_values) self.main_widget.update_items_cache(self.all_values)
else: else:
val = self.get_initial_value(book_ids) val = self.get_initial_value(book_ids)
self.initial_val = val = self.normalize_db_val(val) self.initial_val = val = self.normalize_db_val(val)
idx = None idx = None
self.main_widget.blockSignals(True)
for i, c in enumerate(self.all_values): for i, c in enumerate(self.all_values):
if c == val: if c == val:
idx = i idx = i
self.widgets[1].addItem(c) self.main_widget.addItem(c)
self.widgets[1].setEditText('') self.main_widget.setEditText('')
if idx is not None: if idx is not None:
self.widgets[1].setCurrentIndex(idx) self.main_widget.setCurrentIndex(idx)
self.main_widget.blockSignals(False)
def commit(self, book_ids, notify=False): def commit(self, book_ids, notify=False):
if not self.a_c_checkbox.isChecked():
return
if self.col_metadata['is_multiple']: if self.col_metadata['is_multiple']:
remove_all, adding, rtext = self.gui_val remove_all, adding, rtext = self.gui_val
remove = set() remove = set()
@ -740,7 +883,7 @@ class BulkText(BulkBase):
unicode(self.adding_widget.text()), \ unicode(self.adding_widget.text()), \
unicode(self.removing_widget.tags_box.text()) unicode(self.removing_widget.tags_box.text())
val = unicode(self.widgets[1].currentText()).strip() val = unicode(self.main_widget.currentText()).strip()
if not val: if not val:
val = None val = None
return val return val