idnode: Add intsplit filtering (include double ops, too)
This commit is contained in:
parent
c073538e05
commit
b8fa239354
4 changed files with 196 additions and 15 deletions
|
@ -57,7 +57,7 @@ static void
|
|||
api_idnode_grid_conf
|
||||
( htsmsg_t *args, api_idnode_grid_conf_t *conf )
|
||||
{
|
||||
htsmsg_field_t *f;
|
||||
htsmsg_field_t *f, *f2;
|
||||
htsmsg_t *filter, *e;
|
||||
const char *str;
|
||||
|
||||
|
@ -84,11 +84,20 @@ api_idnode_grid_conf
|
|||
if ((v = htsmsg_get_str(e, "value")))
|
||||
idnode_filter_add_str(&conf->filter, k, v, IC_RE);
|
||||
} else if (!strcmp(t, "numeric")) {
|
||||
uint32_t v;
|
||||
if (!htsmsg_get_u32(e, "value", &v)) {
|
||||
int t = str2val(htsmsg_get_str(e, "comparison") ?: "",
|
||||
filtcmptab);
|
||||
idnode_filter_add_num(&conf->filter, k, v, t == -1 ? IC_EQ : t);
|
||||
f2 = htsmsg_field_find(e, "value");
|
||||
if (f2) {
|
||||
int t = str2val(htsmsg_get_str(e, "comparison") ?: "", filtcmptab);
|
||||
if (f2->hmf_type == HMF_DBL) {
|
||||
double dbl;
|
||||
if (!htsmsg_field_get_dbl(f2, &dbl))
|
||||
idnode_filter_add_dbl(&conf->filter, k, dbl, t == -1 ? IC_EQ : t);
|
||||
} else {
|
||||
int64_t v;
|
||||
int64_t intsplit = 0;
|
||||
htsmsg_get_s64(e, "intsplit", &intsplit);
|
||||
if (!htsmsg_field_get_s64(f2, &v))
|
||||
idnode_filter_add_num(&conf->filter, k, v, t == -1 ? IC_EQ : t, intsplit);
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(t, "boolean")) {
|
||||
uint32_t v;
|
||||
|
|
125
src/idnode.c
125
src/idnode.c
|
@ -407,8 +407,54 @@ idnode_get_s64
|
|||
case PT_S64:
|
||||
*s64 = *(int64_t*)ptr;
|
||||
return 0;
|
||||
case PT_DBL:
|
||||
*s64 = *(double*)ptr;
|
||||
return 0;
|
||||
case PT_TIME:
|
||||
*s64 = *(time_t*)ptr;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get field as double
|
||||
*/
|
||||
int
|
||||
idnode_get_dbl
|
||||
( idnode_t *self, const char *key, double *dbl )
|
||||
{
|
||||
const property_t *p = idnode_find_prop(self, key);
|
||||
if (p->islist) return 1;
|
||||
if (p) {
|
||||
const void *ptr;
|
||||
if (p->get)
|
||||
ptr = p->get(self);
|
||||
else
|
||||
ptr = ((void*)self) + p->off;
|
||||
switch (p->type) {
|
||||
case PT_INT:
|
||||
case PT_BOOL:
|
||||
*dbl = *(int*)ptr;
|
||||
return 0;
|
||||
case PT_U16:
|
||||
*dbl = *(uint16_t*)ptr;
|
||||
return 0;
|
||||
case PT_U32:
|
||||
*dbl = *(uint32_t*)ptr;
|
||||
return 0;
|
||||
case PT_S64:
|
||||
*dbl = *(int64_t*)ptr;
|
||||
return 0;
|
||||
case PT_DBL:
|
||||
*dbl = *(double *)ptr;
|
||||
return 0;
|
||||
case PT_TIME:
|
||||
*dbl = *(time_t*)ptr;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -597,7 +643,16 @@ idnode_cmp_sort
|
|||
}
|
||||
break;
|
||||
case PT_DBL:
|
||||
// TODO
|
||||
{
|
||||
double dbla = 0, dblb = 0;
|
||||
idnode_get_dbl(ina, sort->key, &dbla);
|
||||
idnode_get_dbl(inb, sort->key, &dblb);
|
||||
if (sort->dir == IS_ASC)
|
||||
return dbla - dblb;
|
||||
else
|
||||
return dblb - dbla;
|
||||
}
|
||||
break;
|
||||
case PT_TIME:
|
||||
{
|
||||
time_t ta = 0, tb = 0;
|
||||
|
@ -617,6 +672,31 @@ idnode_cmp_sort
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
idnode_filter_init
|
||||
( idnode_t *in, idnode_filter_t *filter )
|
||||
{
|
||||
idnode_filter_ele_t *f;
|
||||
const property_t *p;
|
||||
|
||||
LIST_FOREACH(f, filter, link) {
|
||||
if (f->type == IF_NUM) {
|
||||
p = idnode_find_prop(in, f->key);
|
||||
if (p) {
|
||||
if (p->type == PT_U32 || p->type == PT_S64 ||
|
||||
p->type == PT_TIME) {
|
||||
int64_t v = f->u.n.n;
|
||||
if (p->intsplit != f->u.n.intsplit) {
|
||||
v = (v / (f->u.n.intsplit <= 0 ? 1 : 0)) * p->intsplit;
|
||||
f->u.n.n = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
f->checked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
idnode_filter
|
||||
( idnode_t *in, idnode_filter_t *filter )
|
||||
|
@ -624,6 +704,8 @@ idnode_filter
|
|||
idnode_filter_ele_t *f;
|
||||
|
||||
LIST_FOREACH(f, filter, link) {
|
||||
if (!f->checked)
|
||||
idnode_filter_init(in, filter);
|
||||
if (f->type == IF_STR) {
|
||||
const char *str;
|
||||
str = idnode_get_display(in, idnode_find_prop(in, f->key));
|
||||
|
@ -655,7 +737,29 @@ idnode_filter
|
|||
int64_t a, b;
|
||||
if (idnode_get_s64(in, f->key, &a))
|
||||
return 1;
|
||||
b = (f->type == IF_NUM) ? f->u.n : f->u.b;
|
||||
b = (f->type == IF_NUM) ? f->u.n.n : f->u.b;
|
||||
switch (f->comp) {
|
||||
case IC_IN:
|
||||
case IC_RE:
|
||||
break; // Note: invalid
|
||||
case IC_EQ:
|
||||
if (a != b)
|
||||
return 1;
|
||||
break;
|
||||
case IC_LT:
|
||||
if (a > b)
|
||||
return 1;
|
||||
break;
|
||||
case IC_GT:
|
||||
if (a < b)
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
} else if (f->type == IF_DBL) {
|
||||
double a, b;
|
||||
if (idnode_get_dbl(in, f->key, &a))
|
||||
return 1;
|
||||
b = f->u.dbl;
|
||||
switch (f->comp) {
|
||||
case IC_IN:
|
||||
case IC_RE:
|
||||
|
@ -699,13 +803,26 @@ idnode_filter_add_str
|
|||
|
||||
void
|
||||
idnode_filter_add_num
|
||||
( idnode_filter_t *filt, const char *key, int64_t val, int comp )
|
||||
( idnode_filter_t *filt, const char *key, int64_t val, int comp, int64_t intsplit )
|
||||
{
|
||||
idnode_filter_ele_t *ele = calloc(1, sizeof(idnode_filter_ele_t));
|
||||
ele->key = strdup(key);
|
||||
ele->type = IF_NUM;
|
||||
ele->comp = comp;
|
||||
ele->u.n = val;
|
||||
ele->u.n.n = val;
|
||||
ele->u.n.intsplit = intsplit;
|
||||
LIST_INSERT_HEAD(filt, ele, link);
|
||||
}
|
||||
|
||||
void
|
||||
idnode_filter_add_dbl
|
||||
( idnode_filter_t *filt, const char *key, double dbl, int comp )
|
||||
{
|
||||
idnode_filter_ele_t *ele = calloc(1, sizeof(idnode_filter_ele_t));
|
||||
ele->key = strdup(key);
|
||||
ele->type = IF_DBL;
|
||||
ele->comp = comp;
|
||||
ele->u.dbl = dbl;
|
||||
LIST_INSERT_HEAD(filt, ele, link);
|
||||
}
|
||||
|
||||
|
|
13
src/idnode.h
13
src/idnode.h
|
@ -100,16 +100,22 @@ typedef struct idnode_filter_ele
|
|||
{
|
||||
LIST_ENTRY(idnode_filter_ele) link; ///< List link
|
||||
|
||||
int checked;
|
||||
char *key; ///< Filter key
|
||||
enum {
|
||||
IF_STR,
|
||||
IF_NUM,
|
||||
IF_DBL,
|
||||
IF_BOOL
|
||||
} type; ///< Filter type
|
||||
union {
|
||||
int b;
|
||||
char *s;
|
||||
int64_t n;
|
||||
struct {
|
||||
int64_t n;
|
||||
int64_t intsplit;
|
||||
} n;
|
||||
double dbl;
|
||||
regex_t re;
|
||||
} u; ///< Filter data
|
||||
enum {
|
||||
|
@ -175,13 +181,16 @@ idnode_perm(idnode_t *self, struct access *a, htsmsg_t *msg_to_write)
|
|||
const char *idnode_get_str (idnode_t *self, const char *key );
|
||||
int idnode_get_u32 (idnode_t *self, const char *key, uint32_t *u32);
|
||||
int idnode_get_s64 (idnode_t *self, const char *key, int64_t *s64);
|
||||
int idnode_get_dbl (idnode_t *self, const char *key, double *dbl);
|
||||
int idnode_get_bool(idnode_t *self, const char *key, int *b);
|
||||
int idnode_get_time(idnode_t *self, const char *key, time_t *tm);
|
||||
|
||||
void idnode_filter_add_str
|
||||
(idnode_filter_t *f, const char *k, const char *v, int t);
|
||||
void idnode_filter_add_num
|
||||
(idnode_filter_t *f, const char *k, int64_t s64, int t);
|
||||
(idnode_filter_t *f, const char *k, int64_t s64, int t, int64_t intsplit);
|
||||
void idnode_filter_add_dbl
|
||||
(idnode_filter_t *f, const char *k, double dbl, int t);
|
||||
void idnode_filter_add_bool
|
||||
(idnode_filter_t *f, const char *k, int b, int t);
|
||||
void idnode_filter_clear
|
||||
|
|
|
@ -107,6 +107,44 @@ tvheadend.idnode_enum_store = function(f)
|
|||
return store;
|
||||
};
|
||||
|
||||
Ext.ux.grid.filter.IntsplitFilter = Ext.extend(Ext.ux.grid.filter.NumericFilter, {
|
||||
|
||||
fieldCls : Ext.form.TextField,
|
||||
|
||||
constructor: function(conf) {
|
||||
this.intsplit = conf.intsplit;
|
||||
if (!conf.fields)
|
||||
conf.fields = {
|
||||
gt: { maskRe: /[0-9\.]/ },
|
||||
lt: { maskRe: /[0-9\.]/ },
|
||||
eq: { maskRe: /[0-9\.]/ }
|
||||
};
|
||||
Ext.ux.grid.filter.IntsplitFilter.superclass.constructor.call(this, conf);
|
||||
},
|
||||
|
||||
getSerialArgs: function () {
|
||||
var key,
|
||||
args = [],
|
||||
values = this.menu.getValue();
|
||||
for (key in values) {
|
||||
var s = values[key].toString().split('.');
|
||||
var v = 0;
|
||||
if (s.length > 0)
|
||||
v = parseInt(s[0]) * this.intsplit;
|
||||
if (s.length > 1)
|
||||
v += parseInt(s[1]);
|
||||
args.push({
|
||||
type: 'numeric',
|
||||
comparison: key,
|
||||
value: v,
|
||||
intsplit: this.intsplit
|
||||
});
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
tvheadend.IdNodeField = function(conf)
|
||||
{
|
||||
/*
|
||||
|
@ -151,7 +189,10 @@ tvheadend.IdNodeField = function(conf)
|
|||
var cfg = conf && this.id in conf ? conf[this.id] : {};
|
||||
var w = 300;
|
||||
var ftype = 'string';
|
||||
if (this.type === 'int' || this.type === 'u32' ||
|
||||
if (this.intsplit) {
|
||||
ftype = 'intsplit';
|
||||
w = 80;
|
||||
} else if (this.type === 'int' || this.type === 'u32' ||
|
||||
this.type === 'u16' || this.type === 's64' ||
|
||||
this.type === 'dbl') {
|
||||
ftype = 'numeric';
|
||||
|
@ -180,7 +221,8 @@ tvheadend.IdNodeField = function(conf)
|
|||
hidden: this.hidden,
|
||||
filter: {
|
||||
type: ftype,
|
||||
dataIndex: this.id
|
||||
dataIndex: this.id,
|
||||
intsplit: this.intsplit
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -307,7 +349,11 @@ tvheadend.IdNodeField = function(conf)
|
|||
case 's32':
|
||||
case 'dbl':
|
||||
case 'time':
|
||||
cons = Ext.form.NumberField;
|
||||
if (this.intsplit) {
|
||||
c['maskRe'] = /[0-9\.]/;
|
||||
cons = Ext.form.TextField;
|
||||
} else
|
||||
cons = Ext.form.NumberField;
|
||||
break;
|
||||
|
||||
/* 'str' and 'perm' */
|
||||
|
|
Loading…
Add table
Reference in a new issue