mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
1) Enhancement 759663
2) Fix notifications of changes to composite column templates so the tag browser stays up to date.
This commit is contained in:
parent
ad72e89072
commit
8c9c8e0880
@ -203,6 +203,8 @@ class CollectionsBookList(BookList):
|
|||||||
val = [orig_val]
|
val = [orig_val]
|
||||||
elif fm['datatype'] == 'text' and fm['is_multiple']:
|
elif fm['datatype'] == 'text' and fm['is_multiple']:
|
||||||
val = orig_val
|
val = orig_val
|
||||||
|
elif fm['datatype'] == 'composite' and fm['is_multiple']:
|
||||||
|
val = [v.strip() for v in val.split(fm['is_multiple'])]
|
||||||
else:
|
else:
|
||||||
val = [val]
|
val = [val]
|
||||||
|
|
||||||
|
@ -483,7 +483,7 @@ class Metadata(object):
|
|||||||
self_tags = self.get(x, [])
|
self_tags = self.get(x, [])
|
||||||
self.set_user_metadata(x, meta) # get... did the deepcopy
|
self.set_user_metadata(x, meta) # get... did the deepcopy
|
||||||
other_tags = other.get(x, [])
|
other_tags = other.get(x, [])
|
||||||
if meta['is_multiple']:
|
if meta['datatype'] == 'text' and meta['is_multiple']:
|
||||||
# Case-insensitive but case preserving merging
|
# Case-insensitive but case preserving merging
|
||||||
lotags = [t.lower() for t in other_tags]
|
lotags = [t.lower() for t in other_tags]
|
||||||
lstags = [t.lower() for t in self_tags]
|
lstags = [t.lower() for t in self_tags]
|
||||||
|
@ -519,6 +519,8 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
|||||||
val = [] if fm['is_multiple'] else ['']
|
val = [] if fm['is_multiple'] else ['']
|
||||||
elif not fm['is_multiple']:
|
elif not fm['is_multiple']:
|
||||||
val = [val]
|
val = [val]
|
||||||
|
elif fm['datatype'] == 'composite':
|
||||||
|
val = [v.strip() for v in val.split(fm['is_multiple'])]
|
||||||
elif field == 'authors':
|
elif field == 'authors':
|
||||||
val = [v.replace('|', ',') for v in val]
|
val = [v.replace('|', ',') for v in val]
|
||||||
else:
|
else:
|
||||||
|
@ -163,8 +163,9 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
elif '*edited' in self.custcols[c]:
|
elif '*edited' in self.custcols[c]:
|
||||||
cc = self.custcols[c]
|
cc = self.custcols[c]
|
||||||
db.set_custom_column_metadata(cc['colnum'], name=cc['name'],
|
db.set_custom_column_metadata(cc['colnum'], name=cc['name'],
|
||||||
label=cc['label'],
|
label=cc['label'],
|
||||||
display = self.custcols[c]['display'])
|
display = self.custcols[c]['display'],
|
||||||
|
notify=False)
|
||||||
if '*must_restart' in self.custcols[c]:
|
if '*must_restart' in self.custcols[c]:
|
||||||
must_restart = True
|
must_restart = True
|
||||||
return must_restart
|
return must_restart
|
||||||
|
@ -41,6 +41,8 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
'text':_('Yes/No'), 'is_multiple':False},
|
'text':_('Yes/No'), 'is_multiple':False},
|
||||||
10:{'datatype':'composite',
|
10:{'datatype':'composite',
|
||||||
'text':_('Column built from other columns'), 'is_multiple':False},
|
'text':_('Column built from other columns'), 'is_multiple':False},
|
||||||
|
11:{'datatype':'*composite',
|
||||||
|
'text':_('Column built from other columns, behaves like tags'), 'is_multiple':True},
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, parent, editing, standard_colheads, standard_colnames):
|
def __init__(self, parent, editing, standard_colheads, standard_colnames):
|
||||||
@ -99,7 +101,9 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
c = parent.custcols[col]
|
c = parent.custcols[col]
|
||||||
self.column_name_box.setText(c['label'])
|
self.column_name_box.setText(c['label'])
|
||||||
self.column_heading_box.setText(c['name'])
|
self.column_heading_box.setText(c['name'])
|
||||||
ct = c['datatype'] if not c['is_multiple'] else '*text'
|
ct = c['datatype']
|
||||||
|
if c['is_multiple']:
|
||||||
|
ct = '*' + ct
|
||||||
self.orig_column_number = c['colnum']
|
self.orig_column_number = c['colnum']
|
||||||
self.orig_column_name = col
|
self.orig_column_name = col
|
||||||
column_numbers = dict(map(lambda x:(self.column_types[x]['datatype'], x),
|
column_numbers = dict(map(lambda x:(self.column_types[x]['datatype'], x),
|
||||||
@ -109,7 +113,7 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
if ct == 'datetime':
|
if ct == 'datetime':
|
||||||
if c['display'].get('date_format', None):
|
if c['display'].get('date_format', None):
|
||||||
self.date_format_box.setText(c['display'].get('date_format', ''))
|
self.date_format_box.setText(c['display'].get('date_format', ''))
|
||||||
elif ct == 'composite':
|
elif ct in ['composite', '*composite']:
|
||||||
self.composite_box.setText(c['display'].get('composite_template', ''))
|
self.composite_box.setText(c['display'].get('composite_template', ''))
|
||||||
sb = c['display'].get('composite_sort', 'text')
|
sb = c['display'].get('composite_sort', 'text')
|
||||||
vals = ['text', 'number', 'date', 'bool']
|
vals = ['text', 'number', 'date', 'bool']
|
||||||
@ -167,7 +171,7 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
getattr(self, 'date_format_'+x).setVisible(col_type == 'datetime')
|
getattr(self, 'date_format_'+x).setVisible(col_type == 'datetime')
|
||||||
for x in ('box', 'default_label', 'label', 'sort_by', 'sort_by_label',
|
for x in ('box', 'default_label', 'label', 'sort_by', 'sort_by_label',
|
||||||
'make_category'):
|
'make_category'):
|
||||||
getattr(self, 'composite_'+x).setVisible(col_type == 'composite')
|
getattr(self, 'composite_'+x).setVisible(col_type in ['composite', '*composite'])
|
||||||
for x in ('box', 'default_label', 'label'):
|
for x in ('box', 'default_label', 'label'):
|
||||||
getattr(self, 'enum_'+x).setVisible(col_type == 'enumeration')
|
getattr(self, 'enum_'+x).setVisible(col_type == 'enumeration')
|
||||||
self.use_decorations.setVisible(col_type in ['text', 'composite', 'enumeration'])
|
self.use_decorations.setVisible(col_type in ['text', 'composite', 'enumeration'])
|
||||||
@ -187,8 +191,8 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
'because these names are reserved for the index of a series column.'))
|
'because these names are reserved for the index of a series column.'))
|
||||||
col_heading = unicode(self.column_heading_box.text()).strip()
|
col_heading = unicode(self.column_heading_box.text()).strip()
|
||||||
col_type = self.column_types[self.column_type_box.currentIndex()]['datatype']
|
col_type = self.column_types[self.column_type_box.currentIndex()]['datatype']
|
||||||
if col_type == '*text':
|
if col_type[0] == '*':
|
||||||
col_type='text'
|
col_type = col_type[1:]
|
||||||
is_multiple = True
|
is_multiple = True
|
||||||
else:
|
else:
|
||||||
is_multiple = False
|
is_multiple = False
|
||||||
@ -249,11 +253,10 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
elif col_type == 'text' and is_multiple:
|
elif col_type == 'text' and is_multiple:
|
||||||
display_dict = {'is_names': self.is_names.isChecked()}
|
display_dict = {'is_names': self.is_names.isChecked()}
|
||||||
|
|
||||||
if col_type in ['text', 'composite', 'enumeration']:
|
if col_type in ['text', 'composite', 'enumeration'] and not is_multiple:
|
||||||
display_dict['use_decorations'] = self.use_decorations.checkState()
|
display_dict['use_decorations'] = self.use_decorations.checkState()
|
||||||
|
|
||||||
if not self.editing_col:
|
if not self.editing_col:
|
||||||
db.field_metadata
|
|
||||||
self.parent.custcols[key] = {
|
self.parent.custcols[key] = {
|
||||||
'label':col,
|
'label':col,
|
||||||
'name':col_heading,
|
'name':col_heading,
|
||||||
|
@ -751,7 +751,7 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
|
|
||||||
if loc not in exclude_fields: # time for text matching
|
if loc not in exclude_fields: # time for text matching
|
||||||
if is_multiple_cols[loc] is not None:
|
if is_multiple_cols[loc] is not None:
|
||||||
vals = item[loc].split(is_multiple_cols[loc])
|
vals = [v.strip() for v in item[loc].split(is_multiple_cols[loc])]
|
||||||
else:
|
else:
|
||||||
vals = [item[loc]] ### make into list to make _match happy
|
vals = [item[loc]] ### make into list to make _match happy
|
||||||
if _match(q, vals, matchkind):
|
if _match(q, vals, matchkind):
|
||||||
|
@ -182,7 +182,7 @@ class CustomColumns(object):
|
|||||||
else:
|
else:
|
||||||
is_category = False
|
is_category = False
|
||||||
if v['is_multiple']:
|
if v['is_multiple']:
|
||||||
is_m = '|'
|
is_m = ',' if v['datatype'] == 'composite' else '|'
|
||||||
else:
|
else:
|
||||||
is_m = None
|
is_m = None
|
||||||
tn = 'custom_column_{0}'.format(v['num'])
|
tn = 'custom_column_{0}'.format(v['num'])
|
||||||
@ -318,7 +318,7 @@ class CustomColumns(object):
|
|||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
|
||||||
def set_custom_column_metadata(self, num, name=None, label=None,
|
def set_custom_column_metadata(self, num, name=None, label=None,
|
||||||
is_editable=None, display=None):
|
is_editable=None, display=None, notify=True):
|
||||||
changed = False
|
changed = False
|
||||||
if name is not None:
|
if name is not None:
|
||||||
self.conn.execute('UPDATE custom_columns SET name=? WHERE id=?',
|
self.conn.execute('UPDATE custom_columns SET name=? WHERE id=?',
|
||||||
@ -340,6 +340,9 @@ class CustomColumns(object):
|
|||||||
|
|
||||||
if changed:
|
if changed:
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
if notify:
|
||||||
|
self.notify('metadata', [])
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
def set_custom_bulk_multiple(self, ids, add=[], remove=[],
|
def set_custom_bulk_multiple(self, ids, add=[], remove=[],
|
||||||
@ -595,7 +598,7 @@ class CustomColumns(object):
|
|||||||
raise ValueError('%r is not a supported data type'%datatype)
|
raise ValueError('%r is not a supported data type'%datatype)
|
||||||
normalized = datatype not in ('datetime', 'comments', 'int', 'bool',
|
normalized = datatype not in ('datetime', 'comments', 'int', 'bool',
|
||||||
'float', 'composite')
|
'float', 'composite')
|
||||||
is_multiple = is_multiple and datatype in ('text',)
|
is_multiple = is_multiple and datatype in ('text', 'composite')
|
||||||
num = self.conn.execute(
|
num = self.conn.execute(
|
||||||
('INSERT INTO '
|
('INSERT INTO '
|
||||||
'custom_columns(label,name,datatype,is_multiple,editable,display,normalized)'
|
'custom_columns(label,name,datatype,is_multiple,editable,display,normalized)'
|
||||||
|
@ -1354,6 +1354,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
cat = tb_cats[category]
|
cat = tb_cats[category]
|
||||||
if cat['datatype'] == 'composite' and \
|
if cat['datatype'] == 'composite' and \
|
||||||
cat['display'].get('make_category', False):
|
cat['display'].get('make_category', False):
|
||||||
|
tids[category] = {}
|
||||||
tcategories[category] = {}
|
tcategories[category] = {}
|
||||||
md.append((category, cat['rec_index'], cat['is_multiple'],
|
md.append((category, cat['rec_index'], cat['is_multiple'],
|
||||||
cat['datatype'] == 'composite'))
|
cat['datatype'] == 'composite'))
|
||||||
@ -1401,9 +1402,18 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
except:
|
except:
|
||||||
prints('get_categories: item', val, 'is not in', cat, 'list!')
|
prints('get_categories: item', val, 'is not in', cat, 'list!')
|
||||||
else:
|
else:
|
||||||
vals = book[dex].split(mult)
|
vals = [v.strip() for v in book[dex].split(mult) if v]
|
||||||
|
if is_comp:
|
||||||
|
for val in vals:
|
||||||
|
if val not in tids:
|
||||||
|
tids[cat][val] = (0, val)
|
||||||
|
item = tcategories[cat].get(val, None)
|
||||||
|
if not item:
|
||||||
|
item = tag_class(val, val)
|
||||||
|
tcategories[cat][val] = item
|
||||||
|
item.c += 1
|
||||||
|
item.id = val
|
||||||
for val in vals:
|
for val in vals:
|
||||||
if not val: continue
|
|
||||||
try:
|
try:
|
||||||
(item_id, sort_val) = tids[cat][val] # let exceptions fly
|
(item_id, sort_val) = tids[cat][val] # let exceptions fly
|
||||||
item = tcategories[cat].get(val, None)
|
item = tcategories[cat].get(val, None)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user