Enumeration type custom columns

This commit is contained in:
Charles Haley 2010-12-02 12:25:16 +00:00
parent 438e0d5305
commit 5cdc87fc89
5 changed files with 78 additions and 32 deletions

View File

@ -15,7 +15,7 @@ from PyQt4.Qt import QComboBox, QLabel, QSpinBox, QDoubleSpinBox, QDateEdit, \
from calibre.utils.date import qt_to_dt, now
from calibre.gui2.widgets import TagsLineEdit, EnComboBox
from calibre.gui2 import UNDEFINED_QDATE
from calibre.gui2 import UNDEFINED_QDATE, error_dialog
from calibre.utils.config import tweaks
class Base(object):
@ -313,22 +313,29 @@ class Series(Base):
class Enumeration(Base):
def setup_ui(self, parent):
self.parent = parent
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
QComboBox(parent)]
w = self.widgets[1]
vals = self.col_metadata['display']['enum_values']
w.addItem('')
for v in vals:
w.addItem(v)
def initialize(self, book_id):
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
if val is None:
val = ''
# This really shouldn't happen
val = self.col_metadata['display']['enum_values'][0]
self.initial_val = val
val = self.normalize_db_val(val)
idx = self.widgets[1].findText(val)
if idx < 0:
error_dialog(self.parent, '',
_('The enumeration "{0}" contains an invalid value '
'that will be set to the default').format(
self.col_metadata['name']),
show=True, show_copy_button=False)
idx = 0
self.widgets[1].setCurrentIndex(idx)
@ -586,20 +593,33 @@ class BulkEnumeration(BulkBase, Enumeration):
def get_initial_value(self, book_ids):
value = None
ret_value = None
dialog_shown = False
for book_id in book_ids:
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
if value is not None and value != val:
return ' nochange '
if val not in self.col_metadata['display']['enum_values']:
if not dialog_shown:
error_dialog(self.parent, '',
_('The enumeration "{0}" contains invalid values '
'that will not appear in the list').format(
self.col_metadata['name']),
show=True, show_copy_button=False)
dialog_shown = True
ret_value = ' nochange '
elif value is not None and value != val:
ret_value = ' nochange '
value = val
if ret_value is None:
return value
return ret_value
def setup_ui(self, parent):
self.parent = parent
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
QComboBox(parent)]
w = self.widgets[1]
vals = self.col_metadata['display']['enum_values']
w.addItem('Do Not Change')
w.addItem('')
for v in vals:
w.addItem(v)
@ -620,14 +640,10 @@ class BulkEnumeration(BulkBase, Enumeration):
if val != self.initial_val and val != ' nochange ':
self.db.set_custom_bulk(book_ids, val, num=self.col_id, notify=notify)
def normalize_ui_val(self, val):
if val == '':
return None
return val
def normalize_db_val(self, val):
if val is None:
return ''
# this really shouldn't happen
val = self.col_metadata['display']['enum_values'][0]
return val
class RemoveTags(QWidget):

View File

@ -262,9 +262,7 @@ class CcEnumDelegate(QStyledItemDelegate): # {{{
def createEditor(self, parent, option, index):
m = index.model()
col = m.column_map[index.column()]
print 'delegate'
editor = QComboBox(parent)
editor.addItem('')
for v in m.custom_columns[col]['display']['enum_values']:
editor.addItem(v)
return editor
@ -272,14 +270,20 @@ class CcEnumDelegate(QStyledItemDelegate): # {{{
def setModelData(self, editor, model, index):
val = unicode(editor.currentText())
if val == '':
val = None
# This shouldn't happen ...
m = index.model()
col = m.column_map[index.column()]
val = m.custom_columns[col]['display']['enum_values'][0]
model.setData(index, QVariant(val), Qt.EditRole)
def setEditorData(self, editor, index):
m = index.model()
val = m.db.data[index.row()][m.custom_columns[m.column_map[index.column()]]['rec_index']]
if val is None:
val = ''
# This shouldn't happen
m = index.model()
col = m.column_map[index.column()]
val = m.custom_columns[col]['display']['enum_values'][0]
idx = editor.findText(val)
if idx < 0:
editor.setCurrentIndex(0)

View File

@ -212,7 +212,7 @@
<item>
<widget class="QLineEdit" name="enum_box">
<property name="toolTip">
<string>A comma-separated list of permitted values. The empty value is always permitted</string>
<string>A comma-separated list of permitted values. The first value is the default</string>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
@ -228,7 +228,7 @@
<string>Default: (nothing)</string>
</property>
<property name="toolTip">
<string>Note that the empty value is always permitted, but is not shown in the list</string>
<string>The first value entered will be the default value for this enumeration</string>
</property>
</widget>
</item>

View File

@ -177,6 +177,8 @@ class CustomColumns(object):
ans = ans.split('|') if ans else []
if data['display'].get('sort_alpha', False):
ans.sort(cmp=lambda x,y:cmp(x.lower(), y.lower()))
elif data['datatype'] == 'enumeration' and ans is None:
ans = data['display']['enum_values'][0]
return ans
def get_custom_extra(self, idx, label=None, num=None, index_is_id=False):
@ -442,7 +444,6 @@ class CustomColumns(object):
if data['normalized']:
if data['datatype'] == 'enumeration' and \
val not in data['display']['enum_values']:
print 'attempt to set enum to', val
return None
if not append or not data['is_multiple']:
self.conn.execute('DELETE FROM %s WHERE book=?'%lt, (id_,))
@ -524,6 +525,18 @@ class CustomColumns(object):
display = data['display']
table, lt = self.custom_table_names(data['num'])
if data['normalized']:
if data['datatype'] == 'enumeration':
query = '%s.value'
line = '''
val_for_enum(\'
SELECT {table}.value FROM {lt}
AS link INNER JOIN {table} ON(link.value={table}.id)
WHERE link.book=?\',
\'{default}\', books.id) custom_{num}
'''.format(lt=lt, table=table,
default=data['display']['enum_values'][0],
num=data['num'])
else:
query = '%s.value'
if data['is_multiple']:
query = 'group_concat(%s.value, "|")'

View File

@ -115,6 +115,17 @@ def pynocase(one, two, encoding='utf-8'):
pass
return cmp(one.lower(), two.lower())
def enum_col_value(select, def_val, id, conn=None):
try:
v = conn.get(select, (id,), all=False)
if v is None:
v = def_val
except Exception, e:
if DEBUG:
print 'enum_col_value failed'
print e
v = def_val
return v
def load_c_extensions(conn, debug=DEBUG):
try:
@ -165,6 +176,8 @@ class DBThread(Thread):
self.conn.create_function('author_to_author_sort', 1,
_author_to_author_sort)
self.conn.create_function('uuid4', 0, lambda : str(uuid.uuid4()))
self.conn.create_function('val_for_enum', 3,
partial(enum_col_value, conn=self.conn))
# Dummy functions for dynamically created filters
self.conn.create_function('books_list_filter', 1, lambda x: 1)