mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Enumeration type custom columns
This commit is contained in:
parent
438e0d5305
commit
5cdc87fc89
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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, "|")'
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user