mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
template box.
This commit is contained in:
parent
cdeb8ade3d
commit
202c9b9d14
@ -95,25 +95,27 @@ class TemplateLineEditor(QLineEdit):
|
|||||||
|
|
||||||
class TagWizard(QDialog):
|
class TagWizard(QDialog):
|
||||||
|
|
||||||
text_template = " strcmp(field('{f}'), '{v}', '{fv}', '{tv}', '{fv}')"
|
text_template = (" strcmp(field('{f}'), '{v}', '{ltv}', '{eqv}', '{gtv}')", True)
|
||||||
text_empty_template = " test(field('{f}'), '{fv}', '{tv}')"
|
text_empty_template = (" test(field('{f}'), '{fv}', '{tv}')", False)
|
||||||
text_re_template = " contains(field('{f}'), '{v}', '{tv}', '{fv}')"
|
text_re_template = (" contains(field('{f}'), '{v}', '{tv}', '{fv}')", False)
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'text.mult' : " str_in_list(field('{f}'), '{mult}', '{v}', '{tv}', '{fv}')",
|
'text.mult' : (" str_in_list(field('{f}'), '{mult}', '{v}', '{tv}', '{fv}')", False),
|
||||||
'text.mult.re' : " in_list(field('{f}'), '{mult}', '^{v}$', '{tv}', '{fv}')",
|
'text.mult.re' : (" in_list(field('{f}'), '{mult}', '^{v}$', '{tv}', '{fv}')", False),
|
||||||
'text.mult.empty' : " test(field('{f}'), '{fv}', '{tv}')",
|
'text.mult.empty' : (" test(field('{f}'), '{fv}', '{tv}')", False),
|
||||||
'text' : text_template,
|
'text' : text_template,
|
||||||
'text.re' : text_re_template,
|
'text.re' : text_re_template,
|
||||||
'text.empty' : text_empty_template,
|
'text.empty' : text_empty_template,
|
||||||
'rating' : " cmp(field('{f}'), '{v}', '{fv}', '{tv}', '{fv}')",
|
'rating' : (" cmp(raw_field('{f}'), '{v}', '{ltv}', '{eqv}', '{gtv}')", True),
|
||||||
'rating.empty' : text_empty_template,
|
'rating.empty' : text_empty_template,
|
||||||
'int' : " cmp(field('{f}'), '{v}', '{fv}', '{tv}', '{fv}')",
|
'int' : (" cmp(raw_field('{f}'), '{v}', '{ltv}', '{eqv}', '{gtv}')", True),
|
||||||
'int.empty' : text_empty_template,
|
'int.empty' : text_empty_template,
|
||||||
'float' : " cmp(field('{f}'), '{v}', '{fv}', '{tv}', '{fv}')",
|
'float' : (" cmp(raw_field('{f}'), '{v}', '{ltv}', '{eqv}', '{gtv}')", True),
|
||||||
'float.empty' : text_empty_template,
|
'float.empty' : text_empty_template,
|
||||||
'bool' : " strcmp(field('{f}'), '{v}', '{fv}', '{tv}', '{fv}')",
|
'bool' : (" strcmp(field('{f}'), '{v}', '{ltv}', '{eqv}', '{gtv}')", True),
|
||||||
'bool.empty' : text_empty_template,
|
'bool.empty' : text_empty_template,
|
||||||
|
'datetime' : (" strcmp(format_date(raw_field('{f}'), 'yyyyMMdd'), format_date('{v}', 'yyyyMMdd'), '{ltv}', '{eqv}', '{gtv}')", True),
|
||||||
|
'datetime.empty' : text_empty_template,
|
||||||
'series' : text_template,
|
'series' : text_template,
|
||||||
'series.re' : text_re_template,
|
'series.re' : text_re_template,
|
||||||
'series.empty' : text_empty_template,
|
'series.empty' : text_empty_template,
|
||||||
@ -128,6 +130,22 @@ class TagWizard(QDialog):
|
|||||||
'comments.empty' : text_empty_template,
|
'comments.empty' : text_empty_template,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
relationals = ('=', '!=', '<', '>', '<=', '>=')
|
||||||
|
relational_truth_vals = {
|
||||||
|
'=': ('', '1', ''),
|
||||||
|
'!=': ('1', '', '1'),
|
||||||
|
'<': ('1', '', ''),
|
||||||
|
'>': ('', '', '1'),
|
||||||
|
'<=': ('1', '1', ''),
|
||||||
|
'>=': ('', '1', '1'),
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def uses_this_wizard(txt):
|
||||||
|
if not txt or txt.startswith('program:\n#tag wizard'):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def __init__(self, parent, db, txt, mi):
|
def __init__(self, parent, db, txt, mi):
|
||||||
QDialog.__init__(self, parent)
|
QDialog.__init__(self, parent)
|
||||||
self.setWindowTitle(_('Coloring Wizard'))
|
self.setWindowTitle(_('Coloring Wizard'))
|
||||||
@ -141,8 +159,7 @@ class TagWizard(QDialog):
|
|||||||
m = db.metadata_for_field(k)
|
m = db.metadata_for_field(k)
|
||||||
if k.endswith('_index') or (
|
if k.endswith('_index') or (
|
||||||
m['kind'] == 'field' and m['name'] and
|
m['kind'] == 'field' and m['name'] and
|
||||||
k not in ('ondevice', 'path', 'size', 'sort') and
|
k not in ('ondevice', 'path', 'size', 'sort')):
|
||||||
m['datatype'] not in ('datetime')):
|
|
||||||
self.columns.append(k)
|
self.columns.append(k)
|
||||||
self.completion_values[k]['dt'] = m['datatype']
|
self.completion_values[k]['dt'] = m['datatype']
|
||||||
if m['is_custom']:
|
if m['is_custom']:
|
||||||
@ -203,11 +220,12 @@ class TagWizard(QDialog):
|
|||||||
h.setAlignment(Qt.AlignCenter)
|
h.setAlignment(Qt.AlignCenter)
|
||||||
l.addWidget(h, 0, 2, 1, 1)
|
l.addWidget(h, 0, 2, 1, 1)
|
||||||
|
|
||||||
h = QLabel(_('not'))
|
h = QLabel(_('op'))
|
||||||
h.setToolTip('<p>' +
|
h.setToolTip('<p>' +
|
||||||
_('Check this box to indicate that the value must <b>not</b> match '
|
_('Use this box to tell what comparison operation to use. Some '
|
||||||
'to use the color. For example, you can check if a tag does '
|
'comparisons cannot be used with certain options. For example, '
|
||||||
'not exist by entering that tag and checking this box.') + '</p>')
|
'if regular expressions are used, only equals and not equals '
|
||||||
|
'are valid.') + '</p>')
|
||||||
h.setAlignment(Qt.AlignCenter)
|
h.setAlignment(Qt.AlignCenter)
|
||||||
l.addWidget(h, 0, 3, 1, 1)
|
l.addWidget(h, 0, 3, 1, 1)
|
||||||
|
|
||||||
@ -246,7 +264,7 @@ class TagWizard(QDialog):
|
|||||||
l.addWidget(c, 0, 7, 1, 1)
|
l.addWidget(c, 0, 7, 1, 1)
|
||||||
|
|
||||||
self.andboxes = []
|
self.andboxes = []
|
||||||
self.notboxes = []
|
self.opboxes = []
|
||||||
self.tagboxes = []
|
self.tagboxes = []
|
||||||
self.colorboxes = []
|
self.colorboxes = []
|
||||||
self.reboxes = []
|
self.reboxes = []
|
||||||
@ -284,13 +302,17 @@ class TagWizard(QDialog):
|
|||||||
w.setText(_('is'))
|
w.setText(_('is'))
|
||||||
l.addWidget(w, i, 2, 1, 1)
|
l.addWidget(w, i, 2, 1, 1)
|
||||||
|
|
||||||
create_widget(QCheckBox, self.notboxes, l, i, 3, None)
|
w = create_widget(QComboBox, self.opboxes, l, i, 3, None)
|
||||||
|
w.setMaximumWidth(40)
|
||||||
|
|
||||||
w = create_widget(QCheckBox, self.emptyboxes, l, i, 4, None)
|
w = create_widget(QCheckBox, self.emptyboxes, l, i, 4, None)
|
||||||
w.stateChanged.connect(partial(self.empty_box_changed, line=i-1))
|
w.stateChanged.connect(partial(self.empty_box_changed, line=i-1))
|
||||||
|
|
||||||
create_widget(MultiCompleteLineEdit, self.tagboxes, l, i, 5, None, align=0)
|
create_widget(MultiCompleteLineEdit, self.tagboxes, l, i, 5, None, align=0)
|
||||||
create_widget(QCheckBox, self.reboxes, l, i, 6, None)
|
|
||||||
|
w = create_widget(QCheckBox, self.reboxes, l, i, 6, None)
|
||||||
|
w.stateChanged.connect(partial(self.re_box_changed, line=i-1))
|
||||||
|
|
||||||
create_widget(QComboBox, self.colorboxes, l, i, 7, self.colors)
|
create_widget(QComboBox, self.colorboxes, l, i, 7, self.colors)
|
||||||
|
|
||||||
w = create_widget(QLabel, None, l, maxlines+1, 5, None)
|
w = create_widget(QLabel, None, l, maxlines+1, 5, None)
|
||||||
@ -315,20 +337,23 @@ class TagWizard(QDialog):
|
|||||||
if len(vals) == 2:
|
if len(vals) == 2:
|
||||||
t, c = vals
|
t, c = vals
|
||||||
f = 'tags'
|
f = 'tags'
|
||||||
a = n = e = re = False
|
a = re = e = 0
|
||||||
|
op = '='
|
||||||
else:
|
else:
|
||||||
t,c,f,re,a,n,e = vals
|
t,c,f,re,a,op,e = vals
|
||||||
try:
|
try:
|
||||||
self.colboxes[i].setCurrentIndex(self.colboxes[i].findText(f))
|
self.colboxes[i].setCurrentIndex(self.colboxes[i].findText(f))
|
||||||
self.colorboxes[i].setCurrentIndex(
|
self.colorboxes[i].setCurrentIndex(
|
||||||
self.colorboxes[i].findText(c))
|
self.colorboxes[i].findText(c))
|
||||||
self.tagboxes[i].setText(t)
|
self.tagboxes[i].setText(t)
|
||||||
self.reboxes[i].setChecked(re == '2')
|
self.reboxes[i].setChecked(re == '2')
|
||||||
self.andboxes[i].setChecked(a == '2')
|
|
||||||
self.notboxes[i].setChecked(n == '2')
|
|
||||||
self.emptyboxes[i].setChecked(e == '2')
|
self.emptyboxes[i].setChecked(e == '2')
|
||||||
|
self.andboxes[i].setChecked(a == '2')
|
||||||
|
self.opboxes[i].setCurrentIndex(self.opboxes[i].findText(op))
|
||||||
i += 1
|
i += 1
|
||||||
except:
|
except:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
w = QLabel(_('Preview'))
|
w = QLabel(_('Preview'))
|
||||||
@ -357,26 +382,6 @@ class TagWizard(QDialog):
|
|||||||
_('EXCEPTION'), self.mi)
|
_('EXCEPTION'), self.mi)
|
||||||
self.test_box.setText(t)
|
self.test_box.setText(t)
|
||||||
|
|
||||||
def column_changed(self, s, line=None):
|
|
||||||
k = unicode(s)
|
|
||||||
if k in self.completion_values:
|
|
||||||
valbox = self.tagboxes[line]
|
|
||||||
valbox.update_items_cache(self.completion_values[k]['v'])
|
|
||||||
if self.completion_values[k]['m']:
|
|
||||||
valbox.set_separator(', ')
|
|
||||||
else:
|
|
||||||
valbox.set_separator(None)
|
|
||||||
|
|
||||||
dt = self.completion_values[k]['dt']
|
|
||||||
if dt in ('int', 'float', 'rating', 'bool'):
|
|
||||||
self.reboxes[line].setChecked(0)
|
|
||||||
self.reboxes[line].setEnabled(False)
|
|
||||||
else:
|
|
||||||
self.reboxes[line].setEnabled(True)
|
|
||||||
else:
|
|
||||||
valbox.update_items_cache([])
|
|
||||||
valbox.set_separator(None)
|
|
||||||
|
|
||||||
def generate_program(self):
|
def generate_program(self):
|
||||||
res = ("program:\n#tag wizard -- do not directly edit\n"
|
res = ("program:\n#tag wizard -- do not directly edit\n"
|
||||||
" first_non_empty(\n")
|
" first_non_empty(\n")
|
||||||
@ -384,9 +389,9 @@ class TagWizard(QDialog):
|
|||||||
was_and = had_line = False
|
was_and = had_line = False
|
||||||
|
|
||||||
line = 0
|
line = 0
|
||||||
for tb, cb, fb, reb, ab, nb, eb in zip(
|
for tb, cb, fb, reb, ab, ob, eb in zip(
|
||||||
self.tagboxes, self.colorboxes, self.colboxes,
|
self.tagboxes, self.colorboxes, self.colboxes,
|
||||||
self.reboxes, self.andboxes, self.notboxes, self.emptyboxes):
|
self.reboxes, self.andboxes, self.opboxes, self.emptyboxes):
|
||||||
f = unicode(fb.currentText())
|
f = unicode(fb.currentText())
|
||||||
if not f:
|
if not f:
|
||||||
continue
|
continue
|
||||||
@ -394,14 +399,11 @@ class TagWizard(QDialog):
|
|||||||
dt = self.completion_values[f]['dt']
|
dt = self.completion_values[f]['dt']
|
||||||
c = unicode(cb.currentText()).strip()
|
c = unicode(cb.currentText()).strip()
|
||||||
re = reb.checkState()
|
re = reb.checkState()
|
||||||
a = ab.checkState()
|
a = ab.checkState()
|
||||||
n = nb.checkState()
|
op = unicode(ob.currentText())
|
||||||
e = eb.checkState()
|
e = eb.checkState()
|
||||||
line += 1
|
line += 1
|
||||||
|
|
||||||
tval = '' if n == 2 else '1'
|
|
||||||
fval = '1' if n == 2 else ''
|
|
||||||
|
|
||||||
if m:
|
if m:
|
||||||
tags = [t.strip() for t in unicode(tb.text()).split(m) if t.strip()]
|
tags = [t.strip() for t in unicode(tb.text()).split(m) if t.strip()]
|
||||||
if re == 2:
|
if re == 2:
|
||||||
@ -428,8 +430,15 @@ class TagWizard(QDialog):
|
|||||||
lines[-1] += ','
|
lines[-1] += ','
|
||||||
|
|
||||||
key = dt + ('.mult' if m else '') + ('.empty' if e else '') + ('.re' if re else '')
|
key = dt + ('.mult' if m else '') + ('.empty' if e else '') + ('.re' if re else '')
|
||||||
template = self.templates[key]
|
tval = '1' if op == '=' else ''
|
||||||
lines.append(template.format(v=tags, f=f, tv=tval, fv=fval, mult=m))
|
fval = '' if op == '=' else '1'
|
||||||
|
template, is_relational = self.templates[key]
|
||||||
|
if is_relational:
|
||||||
|
ltv, eqv, gtv = self.relational_truth_vals[op]
|
||||||
|
else:
|
||||||
|
ltv, eqv, gtv = (None, None, None)
|
||||||
|
lines.append(template.format(v=tags, f=f, tv=tval, fv=fval, mult=m,
|
||||||
|
ltv=ltv, eqv=eqv, gtv=gtv))
|
||||||
|
|
||||||
if a == 2:
|
if a == 2:
|
||||||
was_and = True
|
was_and = True
|
||||||
@ -444,9 +453,9 @@ class TagWizard(QDialog):
|
|||||||
res += ')\n'
|
res += ')\n'
|
||||||
self.template = res
|
self.template = res
|
||||||
res = ''
|
res = ''
|
||||||
for tb, cb, fb, reb, ab, nb, eb in zip(
|
for tb, cb, fb, reb, ab, ob, eb in zip(
|
||||||
self.tagboxes, self.colorboxes, self.colboxes,
|
self.tagboxes, self.colorboxes, self.colboxes,
|
||||||
self.reboxes, self.andboxes, self.notboxes, self.emptyboxes):
|
self.reboxes, self.andboxes, self.opboxes, self.emptyboxes):
|
||||||
t = unicode(tb.text()).strip()
|
t = unicode(tb.text()).strip()
|
||||||
if t.endswith(','):
|
if t.endswith(','):
|
||||||
t = t[:-1]
|
t = t[:-1]
|
||||||
@ -454,15 +463,57 @@ class TagWizard(QDialog):
|
|||||||
f = unicode(fb.currentText())
|
f = unicode(fb.currentText())
|
||||||
re = unicode(reb.checkState())
|
re = unicode(reb.checkState())
|
||||||
a = unicode(ab.checkState())
|
a = unicode(ab.checkState())
|
||||||
n = unicode(nb.checkState())
|
op = unicode(ob.currentText())
|
||||||
e = unicode(eb.checkState())
|
e = unicode(eb.checkState())
|
||||||
if f and (t or e) and (a == '2' or c):
|
if f and (t or e) and (a == '2' or c):
|
||||||
res += '#' + t + ':|:' + c + ':|:' + f + ':|:' + re + ':|:' + \
|
res += '#' + t + ':|:' + c + ':|:' + f + ':|:' + re + ':|:' + \
|
||||||
a + ':|:' + n + ':|:' + e + '\n'
|
a + ':|:' + op + ':|:' + e + '\n'
|
||||||
res += '#else:' + else_txt + '\n'
|
res += '#else:' + else_txt + '\n'
|
||||||
self.template += res
|
self.template += res
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def column_changed(self, s, line=None):
|
||||||
|
k = unicode(s)
|
||||||
|
valbox = self.tagboxes[line]
|
||||||
|
if k in self.completion_values:
|
||||||
|
valbox.update_items_cache(self.completion_values[k]['v'])
|
||||||
|
if self.completion_values[k]['m']:
|
||||||
|
valbox.set_separator(', ')
|
||||||
|
else:
|
||||||
|
valbox.set_separator(None)
|
||||||
|
|
||||||
|
dt = self.completion_values[k]['dt']
|
||||||
|
if dt in ('int', 'float', 'rating', 'bool'):
|
||||||
|
self.reboxes[line].setChecked(0)
|
||||||
|
self.reboxes[line].setEnabled(False)
|
||||||
|
else:
|
||||||
|
self.reboxes[line].setEnabled(True)
|
||||||
|
self.fill_in_opbox(line)
|
||||||
|
else:
|
||||||
|
valbox.update_items_cache([])
|
||||||
|
valbox.set_separator(None)
|
||||||
|
|
||||||
|
def fill_in_opbox(self, line):
|
||||||
|
opbox = self.opboxes[line]
|
||||||
|
opbox.clear()
|
||||||
|
k = unicode(self.colboxes[line].currentText())
|
||||||
|
if not k:
|
||||||
|
return
|
||||||
|
if k in self.completion_values:
|
||||||
|
rebox = self.reboxes[line]
|
||||||
|
ebox = self.emptyboxes[line]
|
||||||
|
idx = opbox.currentIndex()
|
||||||
|
if self.completion_values[k]['m'] or \
|
||||||
|
rebox.checkState() == 2 or ebox.checkState() == 2:
|
||||||
|
opbox.addItems(self.relationals[0:2])
|
||||||
|
idx = idx if idx < 2 else 0
|
||||||
|
else:
|
||||||
|
opbox.addItems(self.relationals)
|
||||||
|
opbox.setCurrentIndex(max(idx, 0))
|
||||||
|
|
||||||
|
def re_box_changed(self, state, line=None):
|
||||||
|
self.fill_in_opbox(line)
|
||||||
|
|
||||||
def empty_box_changed(self, state, line=None):
|
def empty_box_changed(self, state, line=None):
|
||||||
if state == 2:
|
if state == 2:
|
||||||
self.tagboxes[line].setText('')
|
self.tagboxes[line].setText('')
|
||||||
@ -472,6 +523,7 @@ class TagWizard(QDialog):
|
|||||||
else:
|
else:
|
||||||
self.reboxes[line].setEnabled(True)
|
self.reboxes[line].setEnabled(True)
|
||||||
self.tagboxes[line].setEnabled(True)
|
self.tagboxes[line].setEnabled(True)
|
||||||
|
self.fill_in_opbox(line)
|
||||||
|
|
||||||
def and_box_changed(self, state, line=None):
|
def and_box_changed(self, state, line=None):
|
||||||
if state == 2:
|
if state == 2:
|
||||||
|
@ -523,7 +523,7 @@ class BuiltinFormat_date(BuiltinFormatterFunction):
|
|||||||
name = 'format_date'
|
name = 'format_date'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
doc = _('format_date(val, format_string) -- format the value, which must '
|
doc = _('format_date(val, format_string) -- format the value, which must '
|
||||||
'be a date field, using the format_string, returning a string. '
|
'be a date, using the format_string, returning a string. '
|
||||||
'The formatting codes are: '
|
'The formatting codes are: '
|
||||||
'd : the day as number without a leading zero (1 to 31) '
|
'd : the day as number without a leading zero (1 to 31) '
|
||||||
'dd : the day as number with a leading zero (01 to 31) '
|
'dd : the day as number with a leading zero (01 to 31) '
|
||||||
@ -538,7 +538,7 @@ class BuiltinFormat_date(BuiltinFormatterFunction):
|
|||||||
'iso : the date with time and timezone. Must be the only format present')
|
'iso : the date with time and timezone. Must be the only format present')
|
||||||
|
|
||||||
def evaluate(self, formatter, kwargs, mi, locals, val, format_string):
|
def evaluate(self, formatter, kwargs, mi, locals, val, format_string):
|
||||||
if not val:
|
if not val or val == 'None':
|
||||||
return ''
|
return ''
|
||||||
try:
|
try:
|
||||||
dt = parse_date(val)
|
dt = parse_date(val)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user